Fermer

août 17, 2022

Comment fonctionnent les sélecteurs de pseudo-classe CSS :is, :where et :has

Comment fonctionnent les sélecteurs de pseudo-classe CSS :is, :where et :has


Les sélecteurs CSS vous permettent de choisir des éléments par type, attributs ou emplacement dans le document HTML. Ce didacticiel explique trois nouvelles options — :is(), :where() et :has().

Les sélecteurs sont couramment utilisés dans les feuilles de style. L’exemple suivant localise tous <p> éléments de paragraphe et change le poids de la police en gras :

p {
  font-weight: bold;
}

Vous pouvez également utiliser des sélecteurs en JavaScript pour localiser les nœuds DOM :

Sélecteurs de pseudo-classe ciblez les éléments HTML en fonction de leur état actuel. Le plus connu est peut-être :hover, qui applique des styles lorsque le curseur se déplace sur un élément, il est donc utilisé pour mettre en surbrillance les liens et les boutons cliquables. Autre les options populaires incluent:

  • :visited: correspond aux liens visités
  • :target: correspond à un élément ciblé par une URL de document
  • :first-child: cible le premier élément enfant
  • :nth-child: sélectionne des éléments enfants spécifiques
  • :empty: correspond à un élément sans contenu ni élément enfant
  • :checked: correspond à une case à cocher ou à un bouton radio activé
  • :blank: stylise un champ de saisie vide
  • :enabled: allumettes un champ de saisie activé
  • :disabled: correspond à un champ de saisie désactivé
  • :required: cible un champ de saisie obligatoire
  • :valid: correspond à un champ de saisie valide
  • :invalid: correspond à un champ de saisie invalide
  • :playing: cible un élément audio ou vidéo en cours de lecture

Les navigateurs ont récemment reçu trois autres sélecteurs de pseudo-classes…

Le CSS : est un sélecteur de pseudo-classe

Remarque : cela a été spécifié à l’origine comme :matches() et :any()mais :is() est devenu la norme CSS.

Vous devez souvent appliquer le même style à plusieurs éléments. Par exemple, <p> le texte du paragraphe est noir par défaut, mais gris lorsqu’il apparaît dans un <article>, <section>ou <aside>:


p {
  color: #000;
}


article p,
section p,
aside p {
  color: #444;
}

Ceci est un exemple simple, mais des pages plus sophistiquées conduiront à des chaînes de sélection plus compliquées et plus détaillées. Une erreur de syntaxe dans n’importe quel sélecteur pourrait casser le style de tous les éléments.

Les préprocesseurs CSS tels que Sass permettent l’imbrication (qui devient également CSS natif):

article, section, aside {

  p {
    color: #444;
  }

}

Cela crée un code CSS identique, réduit l’effort de frappe et peut éviter les erreurs. Mais:

  • Jusqu’à ce que l’imbrication native arrive, vous aurez besoin d’un outil de construction CSS. Vous voudrez peut-être utiliser une option comme Sass, mais cela peut entraîner des complications pour certaines équipes de développement.

  • La nidification peut causer d’autres problèmes. Il est facile de construire des sélecteurs profondément imbriqués qui deviennent de plus en plus difficiles à lire et à générer des CSS verbeux.

:is() fournit une solution CSS native qui a prise en charge complète dans tous les navigateurs modernes (pas IE):

:is(article, section, aside) p {
  color: #444;
}

Un seul sélecteur peut contenir n’importe quel nombre de :is() pseudo-classes. Par exemple, le sélecteur complexe suivant applique une couleur de texte verte à tous <h1>, <h2>et <p> éléments qui sont des enfants d’un <section> qui a une classe de .primary ou .secondary et qui n’est pas le premier enfant d’un <article>:

article section:not(:first-child):is(.primary, .secondary) :is(h1, h2, p) {
  color: green;
}

Le code équivalent sans :is() requis six sélecteurs CSS :

article section.primary:not(:first-child) h1,
article section.primary:not(:first-child) h2,
article section.primary:not(:first-child) p,
article section.secondary:not(:first-child) h1,
article section.secondary:not(:first-child) h2,
article section.secondary:not(:first-child) p {
  color: green;
}

Notez que :is() ne peut pas correspondre ::before et ::after pseudo-éléments, donc cet exemple de code échouera :


div:is(::before, ::after) {
  display: block;
  content: '';
  width: 1em;
  height: 1em;
  color: blue;
}

Le CSS :where Sélecteur de pseudo-classe

:where() la syntaxe du sélecteur est identique à :is() et est aussi pris en charge dans tous les navigateurs modernes (pas IE). Il en résultera souvent un style identique. Par exemple:

:where(article, section, aside) p {
  color: #444;
}

La différence est spécificité. Spécificité est l’algorithme utilisé pour déterminer quel sélecteur CSS doit remplacer tous les autres. Dans l’exemple suivant, article p est plus spécifique que p seul, de sorte que tous les éléments de paragraphe d’un <article> sera gris :

article p { color: #444; }
p { color: #000; }

Dans le cas de :is(), la spécificité est le sélecteur le plus spécifique trouvé dans ses arguments. Dans le cas de :where()la spécificité est nulle.

Considérez le CSS suivant :

article p {
  color: black;
}

:is(article, section, aside) p {
  color: red;
}

:where(article, section, aside) p {
  color: blue;
}

Appliquons ce CSS au code HTML suivant :

<article>
  <p>paragraph text</p>
</article>

Le texte du paragraphe sera coloré en rouge, comme indiqué dans la démonstration CodePen suivante.

Voir le stylo
Utilisation du sélecteur :is
par SitePoint (@SitePoint)
sur CodePen.

La :is() sélecteur a la même spécificité que article p, mais il vient plus tard dans la feuille de style, donc le texte devient rouge. Il est nécessaire d’enlever à la fois le article p et :is() sélecteurs pour appliquer une couleur bleue, car le :where() sélecteur est moins spécifique que l’un ou l’autre.

Plus de bases de code utiliseront :is() que :where(). Cependant, la spécificité nulle de :where() pourrait être pratique pour les réinitialisations CSS, qui appliquent une ligne de base de styles standard lorsqu’aucun style spécifique n’est disponible. En règle générale, les réinitialisations appliquent une police, une couleur, des remplissages et des marges par défaut.

Ce code de réinitialisation CSS applique une marge supérieure de 1em à <h2> titres sauf si ils sont le premier enfant d’un <article> élément:


h2 {
  margin-block-start: 1em;
}

article :first-child {
  margin-block-start: 0;
}

Tentative de définition d’une coutume <h2> la marge supérieure plus loin dans la feuille de style n’a aucun effet, car article :first-child a une spécificité plus élevée :


h2 {
  margin-block-start: 2em;
}

Vous pouvez résoudre ce problème en utilisant un sélecteur plus spécifique, mais il s’agit de plus de code et pas nécessairement évident pour les autres développeurs. Vous finirez par oublier pourquoi vous en aviez besoin :


article h2:first-child {
  margin-block-start: 2em;
}

Vous pouvez également résoudre le problème en appliquant !important à chaque style, mais évitez de faire ça s’il vous plait ! Cela rend le style et le développement ultérieurs considérablement plus difficiles :


h2 {
  margin-block-start: 2em !important;
}

Un meilleur choix est d’adopter la spécificité nulle de :where() dans votre réinitialisation CSS :


:where(h2) {
  margin-block-start: 1em;
}

:where(article :first-child) {
  margin-block-start: 0;
}

Vous pouvez désormais remplacer n’importe quel style de réinitialisation CSS, quelle que soit sa spécificité ; il n’y a pas besoin d’autres sélecteurs ou !important:


h2 {
  margin-block-start: 2em;
}

Le CSS : a un sélecteur de pseudo-classe

La :has() selector utilise une syntaxe similaire pour :is() et :where()mais il cible un élément qui contient un ensemble d’autres. Par exemple, voici le CSS pour ajouter une bordure bleue de deux pixels à n’importe quel <a> lien contenant un ou plusieurs <img> ou <section> Mots clés:


a:has(img, section) {
  border: 2px solid blue;
}

C’est le développement CSS le plus excitant depuis des décennies ! Les développeurs ont enfin un moyen de cibler les éléments parents !

Le « sélecteur parent » insaisissable a été l’une des fonctionnalités CSS les plus demandées, mais il pose des problèmes de performances pour les fournisseurs de navigateurs, et a donc mis du temps à arriver. En termes simplistes :

  • Les navigateurs appliquent des styles CSS à un élément lorsqu’il est dessiné sur la page. L’élément parent entier doit donc être redessiné lors de l’ajout d’autres éléments enfants.

  • L’ajout, la suppression ou la modification d’éléments en JavaScript peut affecter le style de la page entière jusqu’à la clôture <body>.

En supposant que les fournisseurs ont résolu les problèmes de performances, l’introduction de :has() permet des possibilités qui auraient été impossibles sans JavaScript dans le passé. Par exemple, vous pouvez définir les styles d’un formulaire extérieur <fieldset> et le bouton d’envoi suivant lorsqu’un champ interne requis n’est pas valide :


fieldset:has(:required:invalid) {
  border: 3px solid red;
}


fieldset:has(:required:invalid) + button[type='submit'] {
  opacity: 0.2;
  cursor: not-allowed;
}

Ensemble de champs affiché avec une bordure rouge et un bouton d'envoi désactivé

Cet exemple ajoute un indicateur de sous-menu de lien de navigation qui contient une liste d’éléments de menu enfant :


nav li:has(ol, ul) a::after {
  display: inlne-block;
  content: ">";
}

Ou peut-être pourriez-vous ajouter des styles de débogage, tels que la mise en surbrillance de tous <figure> éléments sans intérieur img:


figure:not(:has(img)) {
  border: 3px solid red;
}

Cinq images d'affilée, avec une bordure rouge autour de l'image manquante

Avant de sauter dans votre éditeur et de refactoriser votre base de code CSS, sachez que :has() est nouveau et le support est plus limité que pour :is() et :where(). Il est disponible en Safari 15.4+ et Chrome 101+ derrière un drapeau expérimental, mais il devrait être largement disponible d’ici 2023.

Résumé du sélecteur

La :is() et :where() les sélecteurs de pseudo-classe simplifient la syntaxe CSS. Vous aurez moins besoin d’imbrication et de préprocesseurs CSS (bien que ces outils offrent d’autres avantages tels que les partiels, les boucles et la minification).

:has() est considérablement plus révolutionnaire et passionnant. La sélection des parents deviendra rapidement populaire et nous oublierons les temps sombres ! Nous publierons une version complète :has() tutoriel lorsqu’il est disponible dans tous les navigateurs modernes.

Si vous souhaitez approfondir les sélecteurs de pseudo-classes CSS – ainsi que toutes les autres choses CSS, telles que Grid et Flexbox – consultez le livre génial Maître CSSde Tiffany Brown.




Source link