Termes CSS clés employés : ::before, :active, :hover, :disabled, :checked, :not().
Compatibilité navigateurs : tous.
Créer un système d’arborescence développable en pur CSS, sans code Javascript ou autre.
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.
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 :
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.
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; }
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;
}
|
---|