Introduction
L’auto numérotation des titres avec Word, OpenOffice, LibreOffice… est facile et bien connu des utilisateurs depuis des décennies.
Comment y parvenir lors de la publication de pages HTML?
CSS est puissant, CSS peut faire le boulot. Toujours investiguer les fonctionnalités CSS avant de démarrer un développement (Javascript…), souvent CSS est capable de couvrir un besoin et très facilement.
Pour auto numéroter les éléments :
- 3 propriétés CSS dont la plupart sont appliquées sur la pseudo classe
::before
:content
,counter-increment
,counter-reset
. - 2 fonctions CSS :
counter()
,counters()
.
Pas plus.
<tag>::before {
content: counter(…);
counter-increment: …;
counter-reset: …;
}
Numérotation des titres
Comment l’auto numérotation des titres est réalisée dans cet article ?
L’auto numérotation des titres est appliquée dans cet article avec uniquement CSS.
Toutes les balises de titres à numéroter sont encapsulées dans la balise main
ici,
bien entendu cela peut être une autre balise parente (body
, div
…):
<main>
<h2>Introduction</h2>
<h2>Numérotation des titres</h2>
<h3>Comment l’auto numérotation des titres est réalisée dans cet article ?</h3>
<h3>Désactiver l’auto numérotation</h3>
<h3>Changer le format</h3>
<h2>Numérotation des listes</h2>
<h2>Pagination</h2>
<h2>Conclusion</h2>
</main>
La balise <h1>
n’est pas numérotée. Dans l’usage, il n’y a qu’une seule balise <h1>
dans
une page et elle sert de titre.
Un compteur est défini pour chaque balise <hx>
et la numérotation est appliquée jusqu’à la balise <h4>
(il est recommandé d’appliquer un niveau de profondeur raisonnable dans les balises de titres).
<h2> | h2counter |
<h3> | h3counter |
<h4> | h4counter |
Les compteurs des sous-titres sont remis à zéro dans la propriété counter-reset
de la balise titre parent :
main { counter-reset: h2counter; }
main h2 { counter-reset: h3counter; }
main h3 { counter-reset: h4counter; }
Dans la pseudo classe ::before
des balises <hx>
, le compteur est incrémenté
et le contenu de la numérotation est défini :
main { counter-reset: h2counter; }
main h2 { counter-reset: h3counter; }
main h3 { counter-reset: h4counter; }
main h2::before {
counter-increment: h2counter;
content: counter(h2counter) ".";
}
main h3::before {
counter-increment: h3counter;
content: counter(h2counter) "." counter(h3counter) ".";
}
main h4::before {
counter-increment: h4counter;
content: counter(h2counter) "." counter(h3counter) "." counter(h4counter) ".";
}
C’est tout.
Désactiver l’auto numérotation
Pour certains titres (introduction, conclusion, annexe…), la désactivation de l’auto numérotation est préférable.
Définir un attribut utilisateur, par exemple data-nocount
:
<h2 data-nocount>Introduction</h2>
et appliquer la numérotation uniquement si la balise ne contient pas cet attribut :
main { counter-reset: h2counter; }
main h2:not([data-nocount]) { counter-reset: h3counter; }
main h3:not([data-nocount]) { counter-reset: h4counter; }
main h2:not([data-nocount])::before {
counter-increment: h2counter;
content: counter(h2counter) ".";
}
main h3:not([data-nocount])::before {
counter-increment: h3counter;
content: counter(h2counter) "." counter(h3counter) ".";
}
main h4:not([data-nocount])::before {
counter-increment: h4counter;
content: counter(h2counter) "." counter(h3counter) "." counter(h4counter) ".";
}
Changer le format
Le format de la numérotation peut être différent dans les pages, exemples : 1.1.1.
, 1-1-1-
.
Un séparateur est alors défini avec une variable, plus personnalisable :
:root {
--sep-num : '-';
}
main { counter-reset: h2counter; }
main h2:not([data-nocount]) { counter-reset: h3counter; }
main h3:not([data-nocount]) { counter-reset: h4counter; }
main h2:not([data-nocount])::before {
counter-increment: h2counter;
content: counter(h2counter) var(--sep-num);
}
main h3:not([data-nocount])::before {
counter-increment: h3counter;
content: counter(h2counter) var(--sep-num) counter(h3counter) var(--sep-num);
}
main h4:not([data-nocount])::before {
counter-increment: h4counter;
content: counter(h2counter) var(--sep-num) counter(h3counter) var(--sep-num) counter(h4counter) var(--sep-num);
}
Pour changer le séparateur de numérotation pour une page, il suffira dans cette page de redéfinir la variable après le chargement du CSS contenant les règles de numérotation :
<link href="./css/style.css" rel="stylesheet"> <style>
:root { --sep-num : '.'; }
</style>
Une variable est également très utile si le format de numérotation est dépendant de la langue. Dans l’exemple ci-dessous, le séparateur par défaut est modifié si le document est en français :
:root {
--sep-num : '.';
}
:lang(fr) { --sep-num : '-'; }
La numérotation peut être d’un autre type que numérique : alphabétique, romain, grec, katakana…
(Mozilla - list-style-type).
Le type est le second argument optionnel de la fonction counter
:
content: counter(h2counter, upper-roman) var(--sep-num);
Numérotation des listes
La balise <ol>
est pratique pour numéroter les éléments dans une liste,
malheureusement la numérotation n’est pas celle attendue lorsque les balises <ol>
sont imbriquées :
|
Une autre problèmatique, on peut souhaiter appliquer une numérotation automatique
sur les éléments d’une liste <ul>
construite par une librairie tierce (javascript…) : TocBot par exemple,
une librairie Javascript pour la génération dynamique de tables des matières.
Les compteurs CSS viennent à la rescousse !
Dans le cas pratique qui suit, la table des matières est générée dans un élément div
(classe js-toc
):
<div class="js-toc">
<ul>
<li><a href="#…">Introduction</a></li>
<li><a href="#…">Numérotation des titres
<ul>
<li><a href="#…">Comment l’auto numérotation des titres est réalisée dans cet article ?</a></li>
<li><a href="#…">Désactiver l’auto numérotation</a></li>
<li><a href="#…">Changer le format</a></li>
</ul>
</li>
<li><a href="#…">Numérotation des listes</a></li>
<li><a href="#…">Pagination</a></li>
<li><a href="#…">Conclusion</a></li>
</ul>
</div>
Pour réaliser la numérotation, un compteur licounter
est réinitialisé
à chaque fois qu’un bloc ul
est créé dans le conteneur de la table des matières (<div class="js-toc">
) :
div[class*="js-toc"] ul {
list-style-type: none;
counter-reset: licounter 0;
}
Pour chaque bloc li
, le compteur est incrémenté et la fonction counters
est utilisée pour remplir le contenu
de la pseudo-class ::before
:
:root {
--sep-num : '.';
}
:lang(fr) { --sep-num : '-'; }
div[class*="js-toc"] ul {
list-style-type: none;
counter-reset: licounter 0;
}
div[class*="js-toc"] ul li::before {
counter-increment: licounter;
content: counters(licounter, var(--sep-num)) var(--sep-num);
padding-right: 8px;
}
La fonction CSS counters
active les compteurs imbriqués et retourne une chaîne concaténée des compteurs en cours.
Pour désactiver l’auto numérotation, comme pour les titres, un attribut utilisateur data-nocount
est défini :
<li data-nocount><a href="#…">Introduction</a></li>
et la numérotation n’est appliquée que si la balise li
ne contient pas l’attribut data-nocount
:
div[class*="js-toc"] ul li:not([data-nocount])::before {
counter-increment: licounter;
content: counters(licounter, var(--sep-num)) var(--sep-num);
padding-right: 8px;
}
Le troisième argument optionnel de la fonction counters
change le type de la numérotation :
content: counters(licounter, var(--sep-num), upper-roman) var(--sep-num);
Pagination
Connaissant cette puissante fonctionnalité, les barres d’outils de pagination sont facilement construites sans avoir à calculer et afficher les compteurs :
ul[class*="paging"] {
list-style-type: none;
counter-reset: pgcounter var(--start-toolbar-paging);
}
ul[class*="paging"] li a:not([data-nocount])::before {
counter-increment: pgcounter;
content: counter(pgcounter);
}
Malheureusement, la variable --start-toolbar-paging
doit être définie auparavant dans la page.
Il est actuellement interdit d’utiliser des valeurs d’attributs qui sont de type string
pour définir des compteurs qui sont de type integer
, les nouveaux niveaux de versions de CSS à venir (CSS 4 ?) couvriront très probablement cette fonctionnalité très attendue.
ul[class*="paging"] {
list-style-type: none;
counter-reset: pgcounter attr(data-count-start);
}
Conclusion
Une conclusion ? Consulter les documentations CSS et rester à jour : puissant, CSS épargne très souvent des heures de programmation et maux de tête.