:empty, une pseudo-classe pas si vide
Dudley Storey montre ici comment utiliser la pseudo-classe :empty, depuis l'application d'un style CSS aux tableaux et aux navigations dynamiques, jusqu'au nettoyage de votre balisage HTML.
Lorsque nous écrivons notre CSS, nous sommes des Zatoïchi du développement web. Nous écrivons de belles déclarations et nous les envoyons vers des documents HTML dans l’espoir qu’ils se rencontrent, mais nous connaissons rarement le contenu spécifique d’un élément sélectionné : la question de savoir combien de mots figurent dans un paragraphe, ou si le paragraphe est vide, relève traditionnellement de la responsabilité de JavaScript ou PHP ou d’autres langages.
Souvent on emploie des langages côté-serveur pour créer du contenu dynamique à l’intérieur d'un conteneur HTML. Lorsque l’opération échoue, c’est aux développeurs front-end qu’il revient de traiter le problème. Plutôt que d’ajouter du code avec JavaScript ou PHP, nous pouvons utiliser CSS pour nos conteneurs vides.
Le mystère de la cellule vide résolu
Les tableaux sont souvent remplis avec des données dynamiques, mais certaines cellules peuvent ne pas contenir d’information. Habituellement, on laisse ces cellules telles quelles, mais on pourrait tout aussi bien mettre en valeur le fait qu’elles ne contiennent rien.
Voici un bon exemple d’un tel cas, un tableau montrant les distances entre villes. Il n’y a évidemment pas de distance entre une ville et elle-même, ce qui produit un certain nombre de cellules vides.
Le balisage de la table serait à peu près celui-ci (j’utilise des raccourcis HTML pour aller plus vite) :
<table>
<caption>Distances Between Cities On The Pacific Rim (miles)</caption>
<col><col><col><col>
<tr><th><th scope=col>Auckland<th scope=col>Papeete<th scope=col>Los Angeles
<tr><th scope=row>Auckland<td><td>2542<td>6518
<tr><th scope=row>Papeete<td>2542<td><td>4114
<tr><th scope=row>Los Angeles<td>6518<td>4114<td></table>
C’est un excellent cas d’utilisation de :empty
puisque les cellules vides doivent être incluses dans le tableau si l’on veut conserver son sens. Avec :empty
il est très facile de cibler les cellules qui n’ont pas de contenu :
td:empty { background: #777; }
Vous avez remarqué la structure du code à la toute fin du tableau, avec la balise fermante </table>
juste après le dernier élément <td>
vide. Si ce n’était pas le cas, la balise <td>
isolée serait considérée comme étant “ouverte” et non pas vide. Une approche alternative serait d’utiliser <td></td>
sans espace entre les deux.
Même si c’est un peu étrange, on peut combiner les sélecteurs :empty et :not()
pour donner un style aux cellules non-vides.
td:not(:empty) { /* styles pour les cellules non vides */ }
Ce serait une approche inhabituelle, puisque notre présupposé est que la majorité des cellules ont du contenu et peuvent être ciblées à l’aide d’un simple sélecteur <td>
, mais c’est une approche valide en CSS.
Réhabiliter le lien manquant
Sur un site, la navigation est souvent générée de façon dynamique, mais parfois incomplète. Il est possible qu’un espace soit réservé pour un lien qui n’apparaît jamais, ou seulement de manière sporadique. Même si cela implique généralement un travail supplémentaire côté serveur, dans l’intervalle il y a une solution CSS simple pour éviter que votre navigation ne ressemble à un sourire aux dents écartées :
nav[role="navigation"] a:empty { display: none; pointer-events: none; }
Un lien comportant un attribut href
mais sans contenu ne sera pas rendu par le navigateur. Donc si nous prenons ce HTML :
<nav role="navigation">
<a href="index.html">Home</a>
<a href="contact.html">Contact</a>
<a href="tools.html">Tools</a>
<a href="classes.html"></a>
</nav>
...et que nous ajoutons le CSS qui précède, le résultat sera que le dernier lien, qui est vide, n’apparaîtra pas (dans ce cas d'ailleurs, le pointer-events
est redondant puisque le lien n'apparaîtra pas, et ne peut donc pas être cliqué).
Exceptions
Attention : l’espace entre les balises ouvrante et fermante est considéré comme une information, de même que des balises (même sans contenu) à l’intérieur de l’élément ciblé, par conséquent les deux éléments suivants ne sont pas considérés comme vides :
<a href="classes.html"> </a>
<a href="classes.html"><span></span></a>
Comme déjà évoqué, les balises qui ne sont pas refermées (même si leur fermeture est optionnelle en HTML) ne sont pas considérées comme vides, même si elles n’ont pas de contenu. Une balise paragraphe isolée est “ouverte” et donc n’est pas vide :
<p>
alors même qu’on aurait certainement (s’il n’y a pas de retour à la ligne) :
<p><p>
Dans ce dernier cas, le premier paragraphe est vide, mais le second (en supposant que rien ne s’ajoute immédiatement après) ne l’est pas.
Les éléments “auto-fermants” sont considérés comme vides : <br>
, <hr>
, <img>
, etc. répondent à :empty
.
Les éléments sont considérés comme vides si leur seul contenu est un commentaire :
<p><!-- ce paragraphe est vide --></p>
Utiliser :empty comme testeur de qualité du code
Inévitablement, les développeurs se laissent aller à la paresse. “Hé, j’ai besoin d’un peu d’espace en-dessous de cet élément. OK, je sais, je vais ajouter un paragraphe vide”.
<p>un contenu réel…</p>
<p></p>
Ou pire encore, une balise <br>
. Ce balisage vide, de remplissage, va à l’encontre des bonnes règles d’écriture de CSS et il est difficile à retrouver. Nous pouvons utiliser :empty
pour obtenir une visualisation rapide du balisage faible :
*:empty, br { border: 2px solid red; }
Compatibilité navigateurs et conclusion
La compatibilité de :empty
est excellente, tous les navigateurs modernes, IE9+ y compris, le reconnaissent.