Styler automatiquement son menu selon la page active

D’un point de vue ergonomie, il est toujours conseillé d’assister au maximum l’internaute dans sa navigation sur un site. Menu simplifié et facilement accessible, fil d’Ariane, habillages spécifiques et effets de survol, tout doit être entrepris pour que l’utilisateur soit, d’une part, toujours en mesure d’identifier l’endroit où il se trouve, d’autre part, qu’il soit toujours capable d’accéder en un minimum de clics au contenu qu’il recherche.

Un logo mêlant les symboles des CSS et de PHP, l'ensemble séparé d'une oblique grise

Sommaire

  1. Ergonomie, économie
  2. Ce qui se conçoit bien s’énonce clairement
  3. Un peu de PHP
    1. Comment lire le nom de la « page active » ?
    2. Injection de classe
  4. Optimisation
    1. Diviser pour mieux coder
    2. Menus à niveaux multiples

Ergonomie, économie [Sommaire]

A cette fin, il est de coutume d’habiller ses menus et autres points de navigation d’effets bien visibles, contrastés, qui se déclenchent lors du passage du curseur. La programmation de ces événements est élémentaire, et se fait grâce aux feuilles de style (CSS) et à la pseudo-classe :hover (W3C Recommandation : les Sélecteurs).

Là où ça se complique un tant soit peu, c’est lorsqu’on veut habiller le menu (ou quoi que ce soit d’autre) selon la page actuellement ouverte, la « page active » comme on dit. Il n’existe en effet aucun sélecteur, aucune pseudo-classe, aucun pseudo-éléments, aucun moyen simple et automatisé permettant de cibler la « page en cours » – et oubliez vite le faux-ami :active qui est fait, lui, pour déclencher son effet lorsque l’internaute clique à la souris ou valide au clavier l’élément habillé… pas vraiment ce que l’on cherche à faire !

Mais alors, doit-on se résoudre à coder un menu différent pour chacune de nos pages, ou tout du moins chacune de nos sections, et appliquer nous-même une classe à la partie du menu concernée ??? Bien sûr que non, le travail à produire serait énorme, la maintenance de la partie navigation de nos sites rendue bien laborieuse, et les informaticiens sont plutôt connus pour être de grands fainéants optimiseurs ! Non, mais c’est pourtant là le début de notre réponse.

Ce qui se conçoit bien s’énonce clairement [Sommaire]

Que cherchons-nous à faire ? Décortiquons un peu notre problème :

  1. il nous faut reconnaître la page active, la page affichée chez l’internaute
  2. il nous faut styler, de manière spécifique, la partie du menu qui mène à cette page

Simple, non ? Et ceci se décrit aussi clairement à l’aide de l’algorithme suivant :

Début, lire le nom de la page active, comparer ce nom à un lien, si ils sont identiques ajouter la classe ici au lien, fin

Un peu de PHP [Sommaire]

Ma première solution utilise un bout de code en PHP, mais j’imagine que du Javascript ferait aussi bien l’affaire. Chacun ses goûts, et personnellement je préfère gérer l’opération côté serveur et livrer mes pages Web avec mes classes déjà en place.

Partons avec un code de menu à un niveau on ne peut plus classique :

1. <ul>
2. 	<li><a href="/index.php">Accueil</a></li>
3. 	<li><a href="/produits.php">Produits</a></li>
4. 	<li><a href="/contact.php">Contact</a></li>
5. </ul>

Comment lire le nom de la « page active » ? [Sommaire]

Les superglobales (PHP Manual : les superglobales) sont des variables prédéfinies, automatiquement créées par PHP à chaque fois qu’une page est chargée, toujours disponibles quel que soit le contexte du script (en début ou en plein milieu de votre code, dans les fonctions que vous créez…). C’est l’une d’entre elles qui va particulièrement nous être utile ici : $_SERVER (PHP Manual : $_SERVER).

Pour avoir une idée précise des valeurs qu’elle peut nous renvoyer suivant l’indice qu’on lui passe, prenez une de vos pages Web au hasard et insérez-y le bout de code suivant, entre la fin de votre section html et le début de votre body par exemple :

1. <?php var_dump ($_SERVER); ?>

Chargez ensuite votre page dans votre navigateur Internet préféré. Les indices qui nous intéressent sont ‘SCRIPT_NAME’ et ‘PHP_SELF’. Les valeurs qu’ils renvoient sont celles que nous recherchons, à savoir « Le nom du fichier du script en cours d’exécution, par rapport à la racine web ». En d’autres termes, le nom de notre page avec l’arborescence !

Remarque : les deux indices renvoient aujourd’hui un résultat identique. Par contre, il est bon de savoir que, lorsque PHP fonctionne en ligne de commande avec une version inférieure à PHP 4.3.0, ‘PHP_SELF’ n’est pas disponible.

Injection de classe [Sommaire]

Nous avons donc notre page active. Maintenant, comme nous l’indique notre algorithme, nous devons la comparer aux différents éléments de notre menu et, si elle correspond à l’un d’eux, injecter la classe "ici" au lien correspondant. Un if simple va nous suffire, soit :

1. <?php
2. 	if ($_SERVER['SCRIPT_NAME'] == "/repertoire(s)/nom-de-notre-page.php") {
3. 		echo "ici";
4. 	}
5. ?>

Ce qui donne une fois ajouté à nos trois liens du menu :

1. <ul>
2. 	<li><a class="<?php if ($_SERVER['SCRIPT_NAME'] == "/index.php") {echo "ici";} ?>" href="/index.php">Accueil</a></li>
3. 	<li><a class="<?php if ($_SERVER['SCRIPT_NAME'] == "/produits.php") {echo "ici";} ?>" href="/produits.php">Produits</a></li>
4. 	<li><a class="<?php if ($_SERVER['SCRIPT_NAME'] == "/contact.php") {echo "ici";} ?>" href="/contact.php">Contact</a></li>
5. </ul>

Optimisation [Sommaire]

Imaginons maintenant que nous ayons plusieurs produits, un grand nombre de produits, organisés en catégories. Si on applique à la lettre ce que nous venons de voir, toutes les URL des pages exposant nos différents produits devront être listées pour déclencher l’injection de la classe "ici" dans le lien du menu « Produits ».

Avec des pages de produits placées dans un répertoire /produits sous les termes « trucs », « machins », « bidules », ça donnera quelque chose comme le code suivant :

3. 	<li><a class="<?php if ( ($_SERVER['SCRIPT_NAME'] == "/produits/trucs.php") || ($_SERVER['SCRIPT_NAME'] == "/produits/machins.php") || ($_SERVER['SCRIPT_NAME'] == "/produits/bidules.php") ) {echo "ici";} ?>" href="/produits.php">Produits</a></li>

Et là, pour l’instant, il n’y a que 3 catégories. Imaginez un peu la longueur du code avec un vrai bon gros catalogue… Un travail titanesque, indigne de la subtilité d’un développeur Web ! Heureusement pour nous, en informatique il y a toujours mille et une manières de parvenir à ses fins – et le cas exposé ici n’échappe pas à cette règle.

Diviser pour mieux coder [Sommaire]

Une alternative simple que, personnellement, j’aime bien utiliser, consiste d’une part à déclarer une ou plusieurs variable(s) spécifiques directement dans mes pages, avant d’appeler le menu, et d’autre part à habiller mes menus de la classe "ici" en fonction de la valeur préalablement attribuée à ces variables. Vous n’avez rien compris ? Avec un exemple cela va vite être plus clair.

Repartons avec notre site de base à 3 pages (Accueil, Produits, Contact). Sur chacune de ces pages je vais déclarer une variable $page_en_cours à laquelle je vais attribuer une valeur en fonction de l’élément du menu que je souhaite décorer, valeurs que je vais simplement nommer respectivement ‘accueil’, ‘produits’ ou ‘contact’.

Soit par exemple le code suivant à placer sur la page Accueil :

1. <?php
2. 	$page_en_cours = 'accueil';
3. 	include('includes/menu.php');
4. ?>

Et le code suivant pour le menu appelé à la ligne 3 :

1. <ul>
2. 	<li><a class="<?php if ($page_en_cours == 'accueil') {echo "ici";} ?>" href="/index.php">Accueil</a></li>
3. 	<li><a class="<?php if ($page_en_cours == 'produits') {echo "ici";} ?>" href="/produits.php">Produits</a></li>
4. 	<li><a class="<?php if ($page_en_cours == 'contact') {echo "ici";} ?>" href="/contact.php">Contact</a></li>
5. </ul>

Limpide, léger, bien plus agréable à lire et à manier, non ? Du coup, maintenant, sur toutes vos pages produits il suffit seulement de déclarer « $page_en_cours = ‘produits’; » pour avoir l’effet escompté. Rien ne sera jamais à ajouter directement à votre menu, vous gérez ça maintenant depuis vos pages !

Menus à niveaux multiples [Sommaire]

Au cas où vous auriez plusieurs niveaux de menu à styler, par exemple des catégories dans vos produits, il suffit de continuer de déclarer dans toutes vos pages catégories $page_en_cours = ‘produits’ pour que « Produits » reste décoré dans le menu, et d’ajouter une seconde variable, par exemple $categorie_en_cours = ‘type1’ pour styler le sous-menu désiré.

Il ne vous reste plus qu’à habiller vos classes ("ici", etc.) à l’aide d’un peu de CSS et le tour est joué.

Maxime Mullet • l’Arpenteur de l’Infosphère

3 réponses à “Styler automatiquement son menu selon la page active

  1. Etudiant

    Génial, je cherchais une solution pour rendre mes menus actifs comprenant dans le code un switch case pour gérer les pages, et ça fonctionne nickel. Le code est un peu imposant mais certes, ça fonctionne.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *