web-dev-qa-db-fra.com

Existe-t-il un moyen CSS d'ajouter une flèche si ul a un enfant ul?

Ma structure de navigation ressemble à ceci:

<div class="menu">
    <ul>
        <li><a href="#">Page 1</a></li>
        <li><a href="#">Page with Subpages</a>
            <ul class="children">
                <li><a href="#">Page with another subpage</a>
                    <ul class="children">
                        <li><a href="#">subsubpage</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li><a href="#">Page 3</a></li>
        <li><a href="#">Page 4</a></li>
    </ul>
</div>

Je souhaite que tous les <li> ayant un enfant de sous-navigation aient une petite flèche vers le bas afin que les utilisateurs sachent que cette page contient des sous-pages.

Est-il possible de détecter en css pur si un <li> a des enfants de ul.children? Dans mon exemple ci-dessus, la flèche vers le bas devrait être appliquée à la "Page avec sous-pages" et la "Page avec une autre sous-page" également.

En ce moment, j'utilise jquery pour résoudre ce problème:

$(function() {
    $('.menu a').each(function() {
        if ( $(this).parent('li').children('ul').size() > 0 ) {
            $(this).append('<span class="dwn">▼</span>');
        }           
    });
});

Existe-t-il un moyen simple et pur en CSS de le faire?

Je vous remercie.

27
matt

Ceci est parfaitement faisable en CSS - 

Votre structure est la suivante: 

 <ul class="menu">
      <li>
           <a href="#">Has arrow</a>
           <ul><li><a href="#"></a></li></ul>
      </li>
      <li>
           <a href="#">Has no arrow</a>
      </li>
  </ul>

Votre CSS sera comme ça - 

   //this adds an arrow to every link
  .menu li > a:after { content: '>'; } 

  // this removes the arrow when the link is the only child
  .menu li > a:only-child:after { content: ''; }   

Si vous voulez créer un menu déroulant contenant une flèche vers le bas sur les éléments de niveau supérieur, puis des flèches vers la droite pour les sous-menus, votre CSS ressemblera à ceci

   // set up the right arrows first
   .menu li > a:after { content: '>'; }

   //set up the downward arrow for top level items
   .menu > li > a:after {content: 'v'; }

   //clear the content if a is only child
   .menu li > a:only-child:after {content: ''; }

Voici un jsfiddle en action - http://jsfiddle.net/w9xnv/2/

88
David

Je pense que le meilleur moyen serait d’ajouter une classe (ou la plage que vous utilisez) à ces lis sur le serveur. 

Une autre solution, mais probablement pas facile et pas propre, est d’ajouter la flèche à tous les uls et de ne les rendre visibles (avec css) que dans ul.children. Vous pouvez ensuite essayer de positionner la flèche devant ou derrière le parent li. Si cela fonctionnera dépendra de la conception.

1
GolezTrol

Pour rester simple, voici la solution que j'aime utiliser:

  1. Placez les étiquettes autour du nom de l'élément faisant office de menu déroulant.

    <div class="menu">
        <ul>
            <li><a href="#"><span>Page with Subpages</span></a>
                <ul class="children">
                    <li><a href="#"><span>Page with another subpage</span></a>
                        <ul class="children">
                            <li><a href="#">subsubpage</a></li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
    
  2. Ajoutez la flèche en utilisant CSS:

    #menu span:after /* DropDown Arrow */
    {
       border: 0.313em solid transparent; /* 5 pixels wide */
       border-bottom: none;  /* helps the drop-down arrow stay in the vertical centre of the parent */
       border-top-color: #cfcfcf;   /* colour of the drop-down arrow */
       content: ''; /* content of the arrow, you want to keep this empty */
       vertical-align: middle;
       display: inline-block;
       position: relative;
       right: -0.313em; /* 5 pixels right of the menu text*/
    }
    

J'espère que cela fonctionne pour toi! Je crois que c'est la méthode la plus simple que j'ai rencontrée!

1
Arcanewinds

Pour les futurs lecteurs! Je me demandais aussi, puis j'ai compris par moi-même

nous ne pouvons pas vérifier si l'élément a des enfants, mais nous pouvons vérifier s'il est vide

li:not(:emtpy):after {
    content: "V";
    color: black;
    position: relative;
    left: 120%;
    /* Well those styles are not best but you get the idea */
}
1
user3870546

Vieille question mais voici comment je le ferais:

.menu li > a:not(:only-child):after { content: '▼'; }

Vous pouvez également le rendre plus joli comme ceci:

.menu li > a:not(:only-child):after { 
    content: '\00a0\00a0▼'; /* add a little spacing so it's not right next to the text */
    font-size: 0.8rem; /* adjust font size so it looks better */
    vertical-align: middle; /* vertical align to middle */
}
1
rotaercz

Il n'y a pas de CSS 'sélecteur de parent'.

Mais voici un code jQuery plus court:

$('.children').prev('li').append('<span class="dwn">▼</span>');

Votre question est similaire à celle-ci:

Sélecteur CSS complexe pour parent d'enfant actif

0
ipim.com

Pour le menu vertical: This js, Fonctionne sur tout = nav.vertical li

$("nav.vertical li:has(ul)").find("a:first").append('<img src="" alt="" class="">');

<nav>
   <ul>
     <li><a href="">Page</a>
         <ul class="children">
           <li><a href="">Post</a></li>
         </ul>
     </li>
   </ul>
</nav>
0

Ceci est juste un raffinement de la réponse rotaercz s. Avec l'aide de CSS Tricks

#cssmenu li > a:not(:only-child)::after {
    content: "";
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid #fff;
    float: right;
}
0
TecBrat

Par exemple 

$(function() {
$('.menu a').each(function() {
    if ( $(this).parent('li').children('ul').size() > 0 ) {
        $(this).append('<span></span>');
    }           
  });
});

et le CSS

.menu li a span {
display: -moz-inline-stack;
display: inline-block;  
zoom: 1;
*display: inline;
vertical-align: middle;
background: url(arrow.png) 0 0 no-repeat;
width: 5px;
height: 3px;
margin-left: 5px;
0
Cristopher

Pour Wordpress, veuillez utiliser les éléments suivants

<?php
/**
* Add arrows to menu items
* @author Bill Erickson
* @link http://www.billerickson.net/code/add-arrows-to-menu-items/
* 
* @param string $item_output, HTML output for the menu item
* @param object $item, menu item object
* @param int $depth, depth in menu structure
* @param object $args, arguments passed to wp_nav_menu()
* @return string $item_output
*/
function be_arrows_in_menus( $item_output, $item, $depth, $args ) {
if( in_array( 'menu-item-has-children', $item->classes ) ) {
    $arrow = 0 == $depth ? '<i class="icon-angle-down"></i>' : '<i class="icon-angle-right"></i>';
    $item_output = str_replace( '</a>', $arrow . '</a>', $item_output );
}
return $item_output;
}
add_filter( 'walker_nav_menu_start_el', 'be_arrows_in_menus', 10, 4 );

Merci à https://www.billerickson.net/code/add-arrows-to-menu-items/

0
Zaid_Sameer