Essayer de coder ← Retour aux sujets

Pseudo-classes : états et positions

:hover

Une pseudo-classe cible un élément dans un certain état ou à une certaine position, sans rien ajouter au HTML.

a:hover
Au survol de la souris
button:focus-visible
Quand l'élément a le focus au clavier
a:active
Pendant le clic
input:checked
Case cochée ou bouton radio sélectionné
input:disabled
Champ désactivé
li:first-child li:last-child
Premier / dernier enfant de son parent
tr:nth-child(even)
Lignes paires (effet zébré)
p:not(.note)
Tous les p sauf ceux de classe note
etats.css
a {
  color: #2563eb;
}

a:hover,
a:focus-visible {
  color: #1d4ed8;
  text-decoration: underline;
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

tbody tr:nth-child(even) {
  background: #f1f5f9;
}

Pseudo-éléments et variables

::before · var()

Un pseudo-élément crée ou cible une *partie* d'un élément. Une variable CSS garde une valeur réutilisable partout.

p::before { content: "→ "; }
Ajoute un contenu décoratif avant le texte
p::first-letter
La première lettre (lettrine)
input::placeholder
Le texte indicatif d'un champ vide
::selection
Le texte sélectionné à la souris
:root { --accent: #ef4a34; }
Définit une variable, visible dans toute la page
color: var(--accent);
Utilise la variable
width: calc(100% - 2rem);
Calcul mêlant des unités différentes
variables.css
:root {
  --accent: #ef4a34;
  --espace: 1rem;
}

.bouton {
  background: var(--accent);
  padding: var(--espace) calc(var(--espace) * 2);
}

.note::before {
  content: "Note : ";
  font-weight: 700;
}
Rendu
Un bouton rouge-orangé avec un espacement double sur les côtés ; chaque paragraphe de classe « note » commence par « Note : » en gras.

🔮 Le cours : aller plus loin avec les sélecteurs

Un sélecteur ne se limite pas à « cet élément » : il peut dire « cet élément quand on le survole », « le troisième de la liste », « la première lettre de ce paragraphe ». Les pseudo-classes (un seul :) expriment un état ou une position, les pseudo-éléments (deux ::) désignent une partie d'un élément, et les variables évitent de répéter les valeurs.

Pseudo-classes d'interaction

Pseudo-classeS'applique quand…
:hoverla souris est au-dessus de l'élément (inexistant sur un écran tactile)
:focusl'élément reçoit le clavier (champ, lien, bouton)
:focus-visiblele focus doit être montré (navigation au clavier) : à préférer à :focus pour les contours
:focus-withinun descendant a le focus (mettre en valeur tout un formulaire)
:activependant l'appui (clic ou toucher)

Pour les liens, l'ordre d'écriture compte (à spécificité égale, le dernier gagne) : a:link, a:visited, a:hover, a:active. Une astuce pour s'en souvenir : « LoVe HAte ». Et quel que soit le style du survol, prévois le même pour :focus-visible : tout le monde n'a pas de souris.

Pseudo-classes de formulaire

:checked, :disabled, :enabled, :required, :optional, :valid, :invalid, :placeholder-shown, :read-only permettent de styler un champ d'après son état, sans JavaScript.

champs.css
input:required {
  border-left: 4px solid #ef4a34;
}

input:valid {
  border-color: #16a34a;
}

/* invalide, mais seulement une fois que l'utilisateur a commencé à écrire */
input:invalid:not(:placeholder-shown) {
  border-color: #dc2626;
}

Pseudo-classes de position

Pseudo-classeCibleExemple
:first-child :last-childle premier / le dernier enfant de son parentli:last-child { border-bottom: 0; }
:nth-child(n)l'enfant en position n, ou selon une formuletr:nth-child(2n) (positions paires)
:nth-of-type(n)comme :nth-child, mais en ne comptant que les éléments de même balisep:nth-of-type(1)
:only-childl'enfant unique
:emptyun élément sans aucun contenup:empty { display: none; }

Les formules de :nth-child : 3 (le troisième), even (pairs), odd (impairs), 2n+1 (1, 3, 5…), 3n (3, 6, 9…), -n+3 (les trois premiers).

not, is, where et has

:not(.note) exclut, :is(h1, h2, h3) regroupe plusieurs sélecteurs sans les répéter, :where() fait de même sans ajouter de spécificité. :has() est un sélecteur de parent : .carte:has(img) cible les cartes qui contiennent une image (disponible dans les navigateurs récents).

logique.css
:is(h1, h2, h3) {
  line-height: 1.2;
}

.carte:has(img) {
  padding: 0;
}

li:not(:last-child) {
  margin-bottom: 0.5rem;
}

Pseudo-éléments

::before et ::after insèrent un contenu décoratif juste avant ou après le contenu de l'élément. Ils ne s'affichent que si la propriété content est définie (même vide, content: "", pour dessiner une forme). Les autres : ::first-letter, ::first-line, ::placeholder, ::selection, ::marker (la puce d'une liste).

pseudo-elements.css
blockquote::before {
  content: "«";
  font-size: 2rem;
}

a[href^="https"]::after {
  content: " ↗";
}

.titre::first-letter {
  font-size: 2em;
  font-weight: 800;
}

::selection {
  background: #fde68a;
}
Le contenu généré n'est pas du vrai contenu

Ce qu'ajoute content n'existe pas dans le HTML : il n'est pas sélectionnable et certains lecteurs d'écran l'ignorent ou le lisent mal. Réserve-le à la décoration (puces, guillemets, flèches), jamais à une information indispensable.

Les variables CSS

Une propriété personnalisée commence par deux tirets (--accent) et se lit avec var(--accent). Déclarée sur :root (l'élément html), elle est disponible dans toute la page. Changer la couleur d'accent d'un site, c'est modifier une ligne. var(--x, valeur) fournit une valeur de secours si la variable n'existe pas.

Contrairement aux variables d'un préprocesseur, elles vivent dans le navigateur : elles suivent la cascade et l'héritage, et on peut les redéfinir sur un élément pour changer son apparence et celle de ses enfants (un thème sombre, une carte d'une autre couleur).

theme.css
:root {
  --fond: #ffffff;
  --texte: #14141a;
}

[data-theme="sombre"] {
  --fond: #14141a;
  --texte: #f7f2ea;
}

body {
  background: var(--fond);
  color: var(--texte);
}
Rendu
La page est blanche avec du texte presque noir. Si l'élément html reçoit data-theme="sombre" (par un petit script), tout s'inverse sans toucher aux autres règles.

calc(), min(), max() et clamp()

calc() mélange les unités : width: calc(100% - 2rem). Les espaces autour de + et - sont obligatoires (100%-2rem est invalide). On peut y utiliser des variables : calc(var(--espace) * 2). min(), max() et clamp(min, préféré, max) choisissent entre plusieurs valeurs (voir Responsive).

⚠️ Erreurs fréquentes

Compter sur :hover pour une information essentielle

Sur un écran tactile, il n'y a pas de survol. Un menu qui ne s'ouvre qu'au :hover est inaccessible au doigt. Utilise aussi :focus-within ou une interaction au clic.

Un pseudo-élément sans content

À éviter
faux.css
.note::before { font-weight: 700; }                       /* rien ne s'affiche */
Correct
correct.css
.note::before { content: "Note : "; font-weight: 700; }

Confondre nth-child et nth-of-type

p:nth-child(2) cible un p qui est le deuxième enfant de son parent (quelle que soit la balise des autres). p:nth-of-type(2) cible le deuxième p parmi les p frères. Si un h2 précède, ils donnent des résultats différents.

Des espaces oubliés dans calc

À éviter
faux.css
width: calc(100%-2rem);    /* invalide : la déclaration est ignorée */
Correct
correct.css
width: calc(100% - 2rem);

Utiliser une variable avant de la définir

var(--accent) sans définition donne une déclaration invalide (la propriété revient à sa valeur par défaut). Fournis une valeur de secours : var(--accent, #ef4a34). Vérifie aussi la portée : une variable déclarée sur .carte n'existe pas en dehors de .carte et de ses descendants.

Simple ou double deux-points

Les pseudo-classes prennent : (a:hover), les pseudo-éléments :: (p::before). Les anciennes écritures :before marchent encore, mais préfère :: pour distinguer les deux familles.

Supprimer le style du focus pour « faire plus propre »

outline: none sans remplacement empêche les utilisateurs du clavier de savoir où ils sont. Écris :focus-visible { outline: 3px solid … } au lieu de supprimer.

📋 Aide-mémoire

  • Interaction : :hover, :focus, :focus-visible, :focus-within, :active ; liens : ordre :link, :visited, :hover, :active.
  • Formulaire : :checked, :disabled, :required, :valid, :invalid, :placeholder-shown.
  • Position : :first-child, :last-child, :nth-child(2n), :nth-of-type(), :not(), :is(), :has().
  • Pseudo-éléments : ::before / ::after (avec content), ::first-letter, ::placeholder, ::selection ; décoratif uniquement.
  • Variables : --nom: valeur; sur :root, var(--nom, secours) ; elles suivent la cascade (thèmes).
  • calc() : espaces autour de + et - ; min(), max(), clamp() pour des valeurs qui s'adaptent.