Pendant longtemps, la notion de pseudo classe se limitait à :hover. Pourtant, cette petite famille de sélecteurs est devenue particulièrement puissante avec l'évolution de CSS.
Une pseudo-classe permet de sélectionner un élément en fonction de son état, de sa position dans le document, de son contexte, de son comportement ou encore de certaines informations qui ne sont pas directement représentées dans le HTML.
Autrement dit, elle permet à CSS de prendre des décisions.
Le W3C définit d'ailleurs les pseudo-classes comme des sélecteurs permettant de cibler des éléments à partir d'informations qui peuvent être extérieures à l'arbre du document ou difficiles à exprimer avec les sélecteurs classiques. Elles peuvent notamment changer dynamiquement lorsque l'utilisateur interagit avec la page.
Une syntaxe extrêmement simple
button:hover {
background: black;
}
Ici, :hover ne crée aucun nouvel élément. Il indique simplement que la règle doit s'appliquer lorsque le bouton se trouve dans l'état « survolé ». C'est précisément ce qui distingue une pseudo-classe d'un pseudo-élément comme ::before ou ::after.
Le tableau des pseudo-classes CSS
Voici une référence regroupant les pseudo-classes CSS actuellement définies dans les spécifications et référencées par MDN. Certaines sont très courantes, d'autres sont spécialisées ou encore expérimentales.
| Pseudo-classe | Fonction | Exemple | Utilisation courante |
|---|---|---|---|
:active | Élément actuellement activé | a:active | Boutons, liens |
:any-link | Tout lien possédant href | a:any-link | Liens |
:autofill | Champ rempli automatiquement | input:autofill | Formulaires |
:checked | Case ou option sélectionnée | input:checked | Checkbox, radio |
:default | Élément sélectionné par défaut | input:default | Formulaires |
:defined | Élément défini | :defined | Web Components |
:dir() | Direction du texte | :dir(rtl) | Multilingue |
:disabled | Élément désactivé | button:disabled | Formulaires |
:empty | Élément sans enfant | div:empty | Nettoyage conditionnel |
:enabled | Élément activé | button:enabled | Formulaires |
:first-child | Premier enfant | li:first-child | Listes |
:first-of-type | Premier élément de son type | p:first-of-type | Structure HTML |
:focus | Élément ayant le focus | input:focus | Formulaires |
:focus-visible | Focus devant être visuellement indiqué | button:focus-visible | Accessibilité |
:focus-within | Élément contenant un élément focalisé | form:focus-within | Formulaires |
:fullscreen | Élément affiché en plein écran | video:fullscreen | Multimédia |
:has() | Sélection selon un descendant/contexte | .card:has(img) | Logique avancée |
:hover | Élément survolé | a:hover | Interactions |
:in-range | Valeur dans la plage autorisée | input:in-range | Formulaires |
:indeterminate | État indéterminé | input:indeterminate | Checkbox/progress |
:invalid | Valeur invalide | input:invalid | Validation |
:is() | Correspond à l'un des sélecteurs | :is(h1,h2,h3) | Simplification |
:lang() | Langue d'un élément | :lang(fr) | Internationalisation |
:last-child | Dernier enfant | li:last-child | Listes |
:last-of-type | Dernier élément de son type | p:last-of-type | Structure HTML |
:link | Lien non encore visité | a:link | Navigation |
:modal | Élément en état modal | dialog:modal | Dialogues |
:not() | Exclut un sélecteur | p:not(.intro) | Exceptions |
:nth-child() | Enfant selon son rang | li:nth-child(2) | Grilles/listes |
:nth-last-child() | Enfant selon son rang depuis la fin | li:nth-last-child(2) | Grilles/listes |
:nth-of-type() | Rang parmi un même type | p:nth-of-type(2) | Structure |
:nth-last-of-type() | Rang depuis la fin parmi un type | p:nth-last-of-type(2) | Structure |
:only-child | Seul enfant | p:only-child | Structure |
:only-of-type | Seul élément de son type | p:only-of-type | Structure |
:open | Élément actuellement ouvert | details:open | Interfaces natives |
:optional | Champ non obligatoire | input:optional | Formulaires |
:out-of-range | Valeur hors plage | input:out-of-range | Formulaires |
:placeholder-shown | Placeholder actuellement visible | input:placeholder-shown | Formulaires |
:playing | Média en lecture | video:playing | Multimédia |
:paused | Média en pause | video:paused | Multimédia |
:popover-open | Popover ouvert | [popover]:popover-open | Popovers |
:read-only | Champ non modifiable | input:read-only | Formulaires |
:read-write | Champ modifiable | input:read-write | Formulaires |
:required | Champ obligatoire | input:required | Formulaires |
:root | Racine du document | :root | Variables CSS |
:scope | Racine du contexte courant | :scope | Sélections contextuelles |
:seeking | Média en recherche | video:seeking | Multimédia |
:stalled | Média bloqué pendant le chargement | video:stalled | Multimédia |
:target | Élément ciblé par l'URL | #contact:target | Ancres |
:valid | Valeur valide | input:valid | Formulaires |
:visited | Lien déjà visité | a:visited | Navigation |
:where() | Comme :is(), sans spécificité | :where(h1,h2,h3) | CSS maintenable |
:user-invalid | Valeur invalide après interaction utilisateur | input:user-invalid | Formulaires |
:user-valid | Valeur valide après interaction utilisateur | input:user-valid | Formulaires |
À cette liste s'ajoutent des pseudo-classes plus spécialisées ou récentes, notamment celles liées aux transitions de vue, aux Web Components, aux popovers, au multimédia ou à certaines fonctionnalités expérimentales. MDN recense notamment :active-view-transition, :active-view-transition-type(), :has-slotted, :host(), :host-context(), :state() et plusieurs pseudo-classes encore expérimentales.
Les pseudo-classes structurelles
C'est probablement l'une des utilisations les plus intéressantes de CSS.
Prenons une liste :
<ul>
<li>Premier</li>
<li>Deuxième</li>
<li>Troisième</li>
<li>Quatrième</li>
</ul>
On peut cibler le premier et le dernier élément sans ajouter de classe HTML :
- li:first-child {
font-weight: bold;
} - li:last-child {
margin-bottom: 0;
}
Mais :nth-child() va beaucoup plus loin :
li:nth-child(2) {
color: red;
}
Ou :
- li:nth-child(odd) {
background: #eee;
}
Ou encore :
- li:nth-child(3n) {
margin-right: 0;
}
Cette dernière notation permet de cibler les éléments 3, 6, 9, 12, etc.
Et CSS permet désormais d'affiner encore cette logique avec une sélection secondaire :
:nth-child(2n of .article)
Ce genre de sélecteur permet de traiter une structure HTML en fonction de sa position sans avoir à injecter artificiellement des classes dans le HTML. Le fonctionnement de :nth-child() et de sa syntaxe An+B est défini dans Selectors Level 4.
Les pseudo-classes fonctionnelles : une évolution importante
Certaines pseudo-classes acceptent des paramètres entre parenthèses.
Les trois plus importantes sont probablement :
- :not()
- :is()
- :where()
Elle permet d'exprimer une exception :
button:not(.primary) {
opacity: .7;
}
On peut donc dire à CSS :
sélectionne tous les boutons sauf ceux qui possèdent .primary.
:is()
Elle permet de regrouper plusieurs sélecteurs :
:is(h1, h2, h3) {
font-family: sans-serif;
}
C'est beaucoup plus propre que :
h1,
h2,
h3 {
font-family: sans-serif;
}
Dans des sélecteurs complexes, l'intérêt devient encore plus évident.
:where()
:where() ressemble à :is(), mais avec une différence fondamentale : son contenu n'ajoute aucune spécificité au sélecteur.
C'est particulièrement intéressant lorsqu'on construit des feuilles CSS destinées à être facilement surchargées.
Le W3C définit précisément cette différence de spécificité entre :is() et :where().
Et puis il y a :has()
:has() est probablement l'une des pseudo-classes les plus intéressantes apparues dans CSS moderne.
Elle permet de sélectionner un élément en fonction de ce qu'il contient ou de ce qui se trouve dans son contexte.
Par exemple :
.card:has(img) {
padding-top: 0;
}
On peut lire cette règle comme :
sélectionne .card lorsqu'elle contient une image.
Autre exemple :
form:has(input:invalid) {
border: 1px solid red;
}
On peut donc modifier le formulaire parce qu'un de ses champs est invalide, sans ajouter de classe au <form> avec JavaScript.
C'est une évolution particulièrement importante : CSS peut désormais exprimer des relations qui nécessitaient auparavant du JavaScript ou une structure HTML spécialement préparée.
Le W3C définit :has() comme une pseudo-classe relationnelle permettant de sélectionner un élément lorsqu'un sélecteur relatif correspondant existe dans son contexte.
Sources et références
- Mozilla Developer Network (MDN), Pseudo-classes — CSS
- W3C, Selectors Level 4
- Mozilla Developer Network (MDN), CSS Selectors
- Mozilla Developer Network (MDN), Pseudo-classes and pseudo-elements
Dans une prochaine partie, nous irons plus loin avec les pseudo-classes avancées et leurs possibilités dans le CSS moderne.
Blog Webdesign & UX
Je conçois des sites internet...
...et des films d'animation
Webdesigner et animateur
de plus de 15 années d'expériences
Une note de 5 étoiles
sur les google reviews
Disponible, réponse
sous 24 heures maximum
Interlocuteur unique
à votre écoute
Des solutions
pour tous les budgets















