Frontend Development

Maîtriser les sélecteurs CSS :has() et :is() pour un style de composants complexes

Pendant des années, les développeurs CSS ont fait face à une limitation persistante : l'incapacité de sélectionner un élément parent en fonction de ses enfants. Nous dépendions fortement de JavaScript pour ajouter des classes utilitaires ou utilisions des mixins SASS fastidieux pour combler ce manque. Cependant, l'introduction des pseudo-classes :has() et :is() a révolutionné notre façon d'écrire les styles. Ces outils puissants permettent d'écrire du code plus expressif, maintenable et efficace. Dans cet article, nous explorerons comment exploiter ces sélecteurs pour relever des défis UI complexes.

Comprendre le sélecteur :is()

La pseudo-classe :is() est essentiellement un sélecteur de regroupement. Elle permet de faire correspondre les éléments qui correspondent à l'un des sélecteurs présents dans sa liste d'arguments. Avant :is(), les développeurs répétaient souvent les sélecteurs pour appliquer des styles partagés, ce qui conduisait à un code verbeux et redondant.

Considérons un scénario où vous souhaitez styliser différemment tous les titres au sein d'un conteneur spécifique. Sans :is(), vous pourriez écrire :


.container h1 {
  color: blue;
}

.container h2 {
  color: blue;
}

.container h3 {
  color: blue;
}

Avec :is(), vous pouvez condenser cela en une seule règle propre :


.container :is(h1, h2, h3) {
  color: blue;
}

Cela réduit non seulement la taille des fichiers, mais améliore également la lisibilité. De plus, :is() hérite de la spécificité de son argument le plus spécifique. Cela est crucial pour comprendre comment il interagit avec d'autres sélecteurs, garantissant que vos styles se propagent exactement comme prévu, sans guerres de spécificité inattendues.

Le changement majeur : le sélecteur :has()

Si :is() concerne le regroupement, :has() concerne le contexte. Souvent appelé « sélecteur parent », :has() sélectionne un élément s'il contient au moins un élément qui correspond au sélecteur fourni en argument. Cette capacité ouvre un monde de solutions purement CSS pour des états qui nécessitaient auparavant JavaScript.

Regardons un exemple pratique : styliser un groupe de formulaire en fonction de la validité de son champ de saisie. Traditionnellement, vous auriez besoin d'un écouteur d'événements sur l'entrée pour ajouter une classe au groupe de formulaire parent. Avec :has(), cela est automatique :


/* Styliser l'étiquette si l'entrée à l'intérieur du groupe de formulaire est valide */
.form-group:has(input:valid) .label {
  color: green;
}

/* Styliser la bordure du groupe de formulaire si son entrée contient une erreur */
.form-group:has(input:invalid) {
  border-color: red;
}

Ce sélecteur est incroyablement puissant pour construire des composants accessibles. Par exemple, vous pouvez mettre en surbrillance visuellement une carte lorsque l'utilisateur interagit avec n'importe quel lien qu'elle contient :


.card:has(:focus-visible) {
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}

Imbrication et combinateurs

:has() prend en charge tous les combinateurs standards, tels que + (frère suivant) et ~ (frère général). Cela permet des expressions logiques complexes. Par exemple, vous pouvez styliser un élément de navigation s'il possède un menu déroulant qui est actuellement ouvert :


nav li:has(~ .dropdown-menu.open) {
  background-color: #f0f0f0;
}

Support des navigateurs et bonnes pratiques

En 2024, tant :has() que :is() bénéficient d'un large support dans les navigateurs modernes, y compris Chrome, Firefox, Safari et Edge. Cependant, si vous devez prendre en charge des navigateurs hérités comme Internet Explorer, envisagez d'utiliser des plugins PostCSS comme postcss-nesting ou de revenir à des solutions JavaScript.

Lors de l'utilisation de ces sélecteurs, gardez à l'esprit les bonnes pratiques suivantes :

  • Évitez le sur-emboîtement : Bien que :has() soit puissant, les sélecteurs profondément imbriqués peuvent devenir difficiles à déboguer.
  • Testez l'accessibilité : Assurez-vous que les indicateurs visuels ajoutés via :has() ne reposent pas uniquement sur la couleur, car cela peut affecter les utilisateurs malvoyants.
  • Performance : Les requêtes :has() complexes peuvent être coûteuses en termes de calcul. Mesurez les performances de vos styles si vous construisez des applications à grande échelle.

Conclusion

Les sélecteurs :is() et :has() marquent une évolution significative des capacités CSS. En permettant un meilleur regroupement et un style contextuel, ils permettent aux développeurs d'écrire des feuilles de style plus propres, plus sémantiques et plus faciles à maintenir. À mesure que ces fonctionnalités deviennent la norme sur toutes les plateformes, les maîtriser n'est plus une option — c'est essentiel pour tout développeur frontend qui souhaite rester à la pointe. Adoptez ces outils pour réduire votre dépendance à JavaScript et créer des interfaces utilisateur plus robustes.

Share: