Créer un menu déroulant avec WordPress

Des fois on ne documente pas son code et c’est un désastre, parce qu’on se retrouve pendant des années à faire et refaire les mêmes choses.

L’objectif est de réaliser un menu déroulant comme vous avez pu souvent en voir sur divers sites internet. Certaines entrées du menu mènent directement vers une autre page du site (je dis page au sens large ça peut être n’importe quoi tant que c’est un lien direct). Mais certaines entrées en contiennent d’autres. Quand on clique sur une de ces entrées un sous-menu avec toutes les entrées contenu apparaît juste en dessous. C’est ça qu’on veut.

Dans l’administration, Apparence et Menus, on peut composer des menus à partir de pages, d’articles, de lien personnalisés et de catégories. On peut même imbriquer des éléments les uns dans les autres, créant ainsi une sorte de hiérarchie.

Côté front-end, la fonction WordPress wp_nav_menu(); va générer ce menu composé dans l’administration. Bon ça va créer une liste imbriquée contenant les différents liens et sur plusieurs niveaux (2). Pour l’instant, c’est moche, mais tout est là. Tout ce qu’on à a faire c’est de styliser tout ça en CSS. Aussi, je veux empécher la navigation si une entrée du menu en contient d’autres. Ça je vais le faire en JavaScript.

Comment distinguer les entrées qui ont un sous-menu de celles qui n’en ont pas, me demanderez-vous. Eh bien WordPress s’en charge lui-même et y ajoute une petite classe .menu-item-has-children, ça tombe bien.

PHP / WordPress

wp_nav_menu();
//Ça et juste ça

JavaScript

//Attention ici c'est un pluriel (Items)
var menuItemsHasChildren = document.querySelectorAll('.menu-item-has-children');

//Et là on en fait un singulier (Item)
menuItemsHasChildren.forEach(function(menuItemHasChildren){
    
    //Attention ça c'est un element li
    var link = menuItemHasChildren.querySelector('a');
    
    link.addEventListener('click',function(e){
        //Prévenir le clic
        e.preventDefault();
        let next = link.nextElementSibling;
        //Là j'ai bien mon sub-menu
        //Reste plus qu'à ajouter une classe "opened"
        //Si elle n'est pas déjà là
        if(next.classList.contains('opened')){
            next.classList.remove('opened');
        }else{
            next.classList.add('opened');
        }

        //Mais on va aussi faire la même chose sur le parent
        let parent = link.parentElement;
        if(parent.classList.contains('clicked')){
            parent.classList.remove('clicked');
        }else{
            parent.classList.add('clicked');
        }

    });
});

CSS (SASS)


div.menu-menu-principal-container{
    transform:translateY(50%);
}

//'menu-principal' c'est le nom de mon menu dans l'admin de WordPress
ul#menu-menu-principal{
    background-color:$blue;
    list-style-type: none;
    display:flex;
    justify-content:flex-end;
    > li.menu-item{
        padding-left:10px;
        padding-right:10px;
        padding-top:20px;
        padding-bottom:20px;
        display:inline-block;
        background-color:$blue;
        position:relative;
        &:hover{
            background-color:lighten($blue,25%);
        }
        &.menu-item-has-children{
            //Classe ajoutée en JavaScript
            &.clicked{
                background-color:lighten($blue,25%);
            }
            > a{
                &:after{
                    content:" ";
                    background-image:url('../img/icons/keyboard_arrow_down-24px.svg');
                    width:24px;
                    height:15px;
                    padding-left:24px;
                    margin-left:5px;
                    //Parce que c'est un svg noir je ne peux pas changer la couleur...
                    //Mais on va utiliser ce tricks : 
                    filter:invert(100%);
                }
            }
        }
    }

    ul.sub-menu{
        display:none;
        &.opened{
            display:block;
        }
        @media screen and (min-width:375px){
            width:375px;
        }
        list-style-type: none;
        padding:0px;
        position:absolute;
        top:100%;
        right:0%;
        > li.menu-item{
            background-color:$red;
            padding:20px;
            text-align: right;
            &:hover{
                background-color:darken($red,5%);
            }
        }
    }

    a{
        color:$silver;
        text-decoration: none;
    }
}

J’espère que tout va bien chez-vous après avoir lu mon code SASS. Bon je n’ai pas pris le temps de l’épurer. Il y a des variables que j’ai déclaré dans un fichier indépendant, et des mixins sont utilisées. Aussi il y a l’utilisation des fonctions darken et lighten mais si vous parlez un minimum l’anglais vous devriez comprendre.

Bref. Ce code vous permet d’obtenir un joli menu déroulant (comme on en fait plus). @+ !