Menu

z-index en CSS : ordre d'empilement et contextes

z-index décide quel élément passe devant quand plusieurs se chevauchent. Découvrez sur quels éléments il fonctionne, comment les contextes d'empilement regroupent les éléments au point qu'un z-index de 9999 peut perdre, ce qui crée un contexte d'empilement et comment réparer un z-index qui ne marche pas.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

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

ValeurSens
auto (par défaut)Empilé au niveau 0 avec ses frères, ne crée pas de contexte d'empilement
0Niveau 0, mais crée un contexte d'empilement
Entier positifDevant les valeurs plus basses
Entier négatifDerriè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 absoluteAvec un z-index autre que auto
position: fixed ou stickyToujours
Élément flex ou gridAvec un z-index autre que auto
opacityInférieure à 1
transform, scale, rotate, translateToute valeur autre que none
filter, backdrop-filterToute valeur autre que none
isolationisolate
mix-blend-modeToute valeur autre que normal
will-changeQui nomme l'une des propriétés ci-dessus
containlayout 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, transform ou filter sur un parent qui enferme soudain son menu déroulant.
  • Des valeurs décimales. z-index: 1.5 est invalide.
  • Croire que z-index: 0 et auto se comportent pareil. 0 crée un contexte d'empilement ; auto non.
  • 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.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER