Ce que fait z-index
Quand des éléments se chevauchent, z-index décide lequel est dessiné devant. Le nombre le plus élevé gagne. Il fonctionne sur les éléments positionnés (toute position sauf static) et sur les éléments flex et grid :
Sans z-index, les éléments placés plus loin dans le HTML sont dessinés par-dessus les précédents : C couvrirait B et B couvrirait A. Les valeurs de z-index inversent cet ordre : A est devant, puis C, puis B.
Les valeurs
| Valeur | Sens |
|---|---|
auto (par défaut) | Empilé au niveau 0 avec ses frères, ne crée pas de contexte d'empilement |
0 | Niveau 0, mais crée un contexte d'empilement |
| Entier positif | Devant les valeurs plus basses |
| Entier négatif | Derrière le niveau 0, et derrière le contenu du parent si le parent forme le contexte d'empilement |
Seuls les entiers sont valides : z-index: 1.5 est ignoré.
Pourquoi un z-index de 9999 peut perdre : les contextes d'empilement
Les valeurs de z-index ne se comparent pas sur toute la page. Les éléments sont regroupés en contextes d'empilement, et un z-index n'ordonne que les éléments d'un même contexte. Le contexte lui-même est ensuite placé comme une seule couche, selon le z-index de l'élément qui l'a créé.
Ci-dessous, le menu déroulant bleu a z-index: 9999, mais il se trouve dans un en-tête avec z-index: 1. Le bandeau vert, frère de cet en-tête, a z-index: 2. Toute la couche de l'en-tête, menu déroulant compris, est sous le bandeau :
Appuyez sur le bouton. Avec z-index: auto, l'en-tête ne forme plus de contexte d'empilement, donc le 9999 du menu est comparé directement au 2 du bandeau, et le menu passe devant. Monter le menu à 99999 n'aurait jamais aidé.
Ce qui crée un contexte d'empilement
Chacune de ces conditions transforme un élément en contexte d'empilement propre, qui enferme le z-index de tout ce qu'il contient :
| Propriété | Condition |
|---|---|
position: relative ou absolute | Avec un z-index autre que auto |
position: fixed ou sticky | Toujours |
| Élément flex ou grid | Avec un z-index autre que auto |
opacity | Inférieure à 1 |
transform, scale, rotate, translate | Toute valeur autre que none |
filter, backdrop-filter | Toute valeur autre que none |
isolation | isolate |
mix-blend-mode | Toute valeur autre que normal |
will-change | Qui nomme l'une des propriétés ci-dessus |
contain | layout ou paint (et strict, content) |
Les plus surprenantes sont opacity et transform : ajouter un fondu ou une animation au survol à un parent peut soudain faire passer son menu déroulant derrière la section suivante.
Le z-index: 10 de l'infobulle devrait la placer au-dessus de la colonne suivante. Mais opacity: 0.99 fait de la première colonne un contexte d'empilement de z-index auto (niveau 0), et la seconde colonne vient plus loin dans le HTML au même niveau : elle est donc peinte par-dessus toute la première colonne, infobulle comprise. Supprimez la ligne opacity et l'infobulle repasse devant.
z-index négatif
Un z-index négatif place un élément derrière ses frères. Si le parent ne forme pas de contexte d'empilement, il peut même passer derrière le fond du parent, ce qui surprend souvent. isolation: isolate sur le parent crée un contexte sans aucun autre effet visuel et garde l'enfant négatif à l'intérieur :
Sans isolation, le cadre ambre passe derrière le fond gris du bouton lui-même, et seul son bord est visible. Avec isolation: isolate, le cadre reste dans le contexte d'empilement du bouton : au-dessus de son fond, sous son texte.
Une échelle de z-index
Choisissez quelques couches nommées pour tout le site au lieu de faire grimper les nombres :
:root {
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 30;
--z-modal: 40;
--z-toast: 50;
}
.modal { position: fixed; z-index: var(--z-modal); }
La plupart des bugs de superposition viennent des contextes d'empilement, pas des nombres : une petite échelle plus isolation: isolate sur les composants qui utilisent z-index en interne règle beaucoup de problèmes. z-index a besoin d'un positionnement pour fonctionner ; la page position le détaille.
Erreurs courantes
- z-index sur un élément static. Ajoutez
position: relative(ou faites-en un élément flex ou grid). - Monter jusqu'à 9999. Si un parent forme un contexte d'empilement placé sous l'élément concurrent, aucune valeur d'enfant ne peut gagner. Cherchez plutôt le contexte.
- Un nouveau
opacity,transformoufiltersur un parent qui enferme soudain son menu déroulant. - Des valeurs décimales.
z-index: 1.5est invalide. - Croire que
z-index: 0etautose comportent pareil.0crée un contexte d'empilement ;autonon. - Des modales dans des composants profondément imbriqués. Affichez-les vers la fin de
<body>(ou utilisez la couche supérieure de l'élément<dialog>), pour qu'aucun contexte ancêtre ne puisse les enfermer.
Questions fréquentes
À quoi sert z-index ?
Il définit l'ordre d'empilement des éléments qui se chevauchent : une valeur plus haute est dessinée devant une valeur plus basse dans le même contexte d'empilement. La valeur par défaut est auto, et les valeurs sont des nombres entiers, négatifs compris.
Pourquoi mon z-index ne fonctionne-t-il pas ?
Soit l'élément n'est pas positionné (z-index demande une position autre que static, ou un enfant flex ou grid), soit il se trouve dans un parent qui forme un contexte d'empilement placé plus bas. Un enfant ne peut jamais passer au-dessus d'un élément sous lequel son contexte d'empilement est placé, quel que soit son propre z-index.
Qu'est-ce qu'un contexte d'empilement ?
Un groupe d'éléments empilés ensemble comme une seule couche. À l'intérieur, les enfants sont ordonnés par leur z-index ; à l'extérieur, tout le groupe est placé selon le z-index de l'élément qui l'a créé.
Qu'est-ce qui crée un contexte d'empilement ?
Entre autres : l'élément racine, un élément positionné avec un z-index autre que auto, position: fixed ou sticky, un enfant flex ou grid avec un z-index, opacity inférieure à 1, transform, filter, isolation: isolate et will-change sur ces propriétés.
z-index fonctionne-t-il sans position ?
Pas sur les éléments block ou inline normaux : position: static l'ignore. Il fonctionne en revanche sur les éléments flex et grid sans aucune position.