#22886 - Note : CSS astuce
En CSS, on peut cibler un élément qui n’a pas d’éléments enfants (et apparaît donc vide) :
div:empty { }
Attention, un élément est « :empty » s’il n’a aucun élément dedans. Cela regarde donc la présence d’éléments HTML, pas du simple texte, ou même juste des espaces (dont les tabulations).
Si le DIV contient un SPAN qui est lui-même vide, cela ne marchera pas non plus.
Cela cible donc ça :
<div></div>
Mais pas ceci :
<div>\t\t</div>
<div><span></span></div>
Dans ce dernier cas, si on veut masquer un tel DIV, il faut faire ça :
div:has(:empty) { }
Cela ciblera les DIV qui contiennent un élément qui soit lui-même :empty.
Dans mon cas, ce n’est pas ce que je veux.
Je veux cibler les DIV qui apparaissent vide à l’écran, peu importe son DOM.
Donc :
– un DIV vide (<div></div>)
– un DIV avec juste des espaces (<div>\t\t</div>)
– un DIV avec des éléments cachés (en "display:none", avec l’attribut [hidden] dans mon cas)
Je veux cibler tout ça plus haut : je veux cibler des DIV qui n’ont *que* des descendants [hidden] (et qui semble donc vide).
Traduit en DOM, il faut réfléchir dans l’autre sens.
Qu’est-ce que je ne veux pas cibler ? Je ne veux pas cibler les DIV avec des éléments qui ne soient pas [hidden].
Le sélecteur pour cibler des DIV qui contient des éléments avec [hidden] est :
div:has([hidden]) {}
Le sélecteur pour cibler des DIV qui ne contiennent QUE des éléments avec [hidden] revient à sélectionner des DIV qui n’ont pas d’éléments sans [hidden].
Cela revient à faire une double négative logique, et ça c’est possible grâce à :not() :
div:not(:has(:not([hidden]))) { }
Sauf que… ça ne marche pas toujours.
Par exemple, si le DIV contient un fils SPAN[hidden], qui lui-même contient un SPAN sans [hidden], cela va le voir et casser le ciblage :
<div>
<span hidden>
<span></span>
</span>
</div>
Ce petit-fils n’est pas visible car son parent est [hidden]. Le DIV semble bien vide, mais il ne sera pas ciblé, et c’est un problème. LA solution est donc de cibler uniquement les éléments enfants du DIV, avec le sélecteur de descendant direct « > » :
div:not(:has(> :not([hidden]))) { }
Et là ça marche. Je cible tous les DIV qui n’ont aucun descendant direct qui ne soit pas [hidden] – donc des DIV qui semblent visuellement vide.
On dit que le CSS n’est pas un langage de programmation. Et c’est vrai. Mais ce n’est pas pour ça que ce n’est pas un sous-langage : on fait aussi de la logique opératoire (AND/OR/NOT…) de bas niveau, et beaucoup de combinaisons de tout ça !
Aussi, ici, on contourne le logique du DOM de CSS (:empty) pour l’appliquer à des éléments qui semblent vides, mais qui ne le sont pas forcément dans le DOM.