Chapitre 2
Interface et menus

Retour Accueil CSS

24 Arborescence développable

Termes CSS clés employés : ::before, :active, :hover, :disabled, :checked, :not().
Compatibilité navigateurs : tous.

Problématique

Créer un système d’arborescence développable en pur CSS, sans code Javascript ou autre.

Résolution théorique

C’est de prime abord un projet un peu ambitieux, dont la résolution est toutefois bien plus simple qu’il n’y paraît. Une arborescence n’est qu’une liste à plusieurs niveaux. Pour gérer le développement ou le masquage d’éléments, il peut être employé un élément HTML INPUT de type chekbox, dont on contrôlera l’état :active, :checked et/ou :disabled.

Résolution pratique

Comme énoncé ci-dessus, le code HTML n’est rien d’autre qu’une liste. Nous créons un élément conteneur div, puis y insérons une liste non ordonnée ul de classe arbre. Dans cet élément, un dossier est un élément li qui renferme un élément ul, lequel renfermera le contenu du dossier.
<div> <ul class=arbre > <li><!-- Ceci est un dossier de premier niveau --> <ul> < !-- contenu du dossier de premier niveau --> </ul> </li> </ul> </div>
Pour faire de cette liste une arborescence développable, un élément input de type checkbox, complété d’un élément label affecté à l’élément input d’après son identifiant sont ajoutés dans l’élément li constituant un dossier :
<li> <input type="checkbox" id="dossier_1" /> <label for="dossier_1">Ceci est un dossier de premier niveau</label> <ul> <!-- contenu du dossier de premier niveau --> </ul> </li>
Pour ajouter d’autres dossiers de premier niveau, vous ajoutez dans l’élément de classe arbre d’autres lignes conçues comme la précédente. En ajoutant un élément li normal (sans éléments input et label), vous ajoutez un élément de premier niveau qui n’est pas un dossier imbriqué développable. Normalement, par définition, les éléments LI enfants directs de la liste arbre devraient tous être des dossiers. Dans toute liste ultérieure ul placée à l’intérieur d’un dossier li, vous pouvez trouver deux types d’éléments : des éléments li dossiers (renfermant eux-mêmes une liste ul) et/ou des éléments li simples.
<div> <ul class=arbre > <li> <input type="checkbox" id="dossier_1" /> <label for="dossier_1"> Ceci est un dossier de premier niveau </label> <ul> <li> <input type="checkbox" id="dossier_1_1" /< <label for="dossier_1_1"> Ceci est un dossier de second niveau </label> <ul> </ul> </li> <li>Elément de premier niveau</LI> <li>Elément de premier niveau</LI> </ul> </li> </ul> </div>
Voici un exemple de ce que donnerait un tel squelette HTML. Remarquez l’ajout de dossiers et d’éléments de contenu :

Dossiers imbriqués développables : structure HTML

Ce squelette présente de nombreux défauts d’apparence et n’est en rien développable. S’il est possible de cocher les cases, cela est sans influence aucune. Il faut passer au code CSS. Première étape, supprimer l’affichage par défaut pour des listes :
ul,li {list-style: none;}
Ensuite, on rend invisible l’élément input en lui affectant une opacité nulle, tandis qu’on définit l’élément label comme étant un bloc en ligne :
.arbre input { position: absolute; opacity: 0; }input .arbre label {display: inline-block;}
Enfin, le secret de la structure développable : par défaut, tout enfant ul d’un élément input n’est pas affiché. Il ne l’est que si l’élément parent input est coché :
.arbre input ~ ul { display: none;} .arbre input:checked ~ ul {display: block;}
Comme le montre la démo suivante, ça fonctionne parfaitement.

Dossiers imbriqués développables (II)

Reconnaissons toutefois que cela manque un peu d’esthétisme et d’ergonomie… Pour améliorer cela, modifions l’apparence du curseur lorsqu’il se trouve sur un dossier (un élément label) afin d’indiquer que cet élément est cliquable :
.arbre label { display: inline-block; cursor: pointer; }
Ensuite, il serait bien d’agrémenter cette arborescence à l’aide des traditionnelles icônes + et – (indiquant qu’un dossier ou développé ou refermé), ainsi que d’une icône de dossier. Plutôt que d’employer des images distinctes, nous allons recourir à un sprite CSS : une image employée en arrière-plan et décalée à chaque fois pour ne faire apparaître que ce qui nous intéresse. L’image en question est celle-ci :

Nous l’ajoutons à l’élément label :
.arbre label { … height: 16px; line-height: 16px; vertical-align: middle; background-position: 18px 0; }
La position d’arrière-plan fait apparaître l’icône de dossier. Remarquez les définitions explicites de hauteur, de hauteur de ligne et d’alignement vertical. Nous l’ajoutons également à un nouvel élément label:before et réglons le décalage horizontal de l’arrière-plan de façon à afficher l’icône du signe + :
.arbre label:before { display: inline-block; cursor: pointer; content: ""; width: 16px; height: 16px; line-height: 16px; vertical-align: middle; margin: 0 22px 0 0; background: url(icons.png) no-repeat; background-position: 0 -32px; }
Enfin, nous modifions la position d’arrière plan lorsque l’élément est cliqué (développé) afin d’afficher l’icône du signe - :
.arbre input:checked + label:before { background-position: 0 -16px; }

Dossiers imbriqués développables (III)

Cette fois, l’aspect est parfaitement satisfaisant. Pour être tout à fait complet toutefois, il reste deux choses à préciser : pouvoir définir lors de l’affichage initial de la page si un dossier doit être par défaut développé ou non, et pour indiquer qu’un élément ou un dossier est désactivé. Dans les deux cas, cela s’effectue dans le code HTML. Dans le second cas un ajout CSS sera nécessaire. Un élément HTML input de type checkbox possède un attribut checked pouvant être fixé à checked ou unchecked (la valeur par défaut). Cela signifie que pour qu’un dossier soit toujours développé, il suffit d’ajouter dans sa balise input l’attribut checked="checked".
<input type="checkbox" id="dossier_1" checked="checked" /> <label for="dossier_1">Ceci est un dossier de premier niveau toujours développé </label>
De même, un élément HTML input possède un attribut disabled pouvant être fixé à disabled ou enabled (la valeur par défaut). Cela signifie qu’un dossier soit désactivé, il suffit d’ajouter dans sa balise input l’attribut disabled="disabled".
<input type="checkbox" id="dossier_2" disabled="disabled" /> <label for="dossier_2">Ce dossier de premier niveau est désactivé</LABEL>
Il est ensuite nécessaire d’ajouter dans le code CSS une définition lorsque input est désactivé. Ici, nous remettons un pointeur « normal » et grisons l’élément label en lui affectant une opacité de 60% :
.arbre input:disabled + label { cursor: default; opacity: .6; }

Dossiers imbriqués développables (IV)


Retour Accueil CSS

© 1999-2014 Fabrice "Fyndhorn Elder" Lemainque