Cours CSS / z-index et contextes d’empilement

Le z-index contrôle la superposition au sein du contexte de superposition pertinent plutôt que d'attribuer à chaque élément une profondeur globale. Un enfant avec un z-index élevé peut rester derrière un élément dans un contexte d'ancêtre supérieur, et le z-index ne peut pas annuler la découpe par overflow.

Séparer le positionnement de l'ordre de superposition

Pour comparer l'ordre de chevauchement, les deux éléments doivent réellement occuper la même zone de l'écran. S'ils sont complètement à gauche et à droite, ou en haut et en bas, changer le z-index ne fera aucune différence. Tout d'abord, vérifiez la position rectangulaire de l'élément dans les outils de développement et déterminez si des zones de chevauchement existent. Pour les références de positionnement des éléments chevauchants, consultez les règles d’espace et de coordonnées de CSS position : relative, absolute, fixed et sticky.

La position détermine la référence de coordonnées et la participation au flux, et le z-index détermine l'avant et l'arrière lors du chevauchement. Modifier les coordonnées avec top et changer l'ordre avec z-index sont des tâches différentes. L'exemple ci-dessous fixe les positions du badge et de la carte puis ne modifie que le z-index du parent, afin que vous puissiez comparer les deux fonctions sans les mélanger.

Le z-index peut être appliqué aux éléments positionnés tels que relative·absolute, et peut être utilisé pour les éléments Flex et Grid même si position: static. Si vous n'attribuez que des nombres aux blocs de flux général ordinaires en vous attendant à des effets, les conditions d'application peuvent ne pas être remplies. Vous pouvez vérifier la signification de la cible et de la valeur dans la description du z-index de MDN.

Comparer les contextes d'empilement en tant que groupes

Un contexte d'empilement regroupe ses descendants pour des comparaisons d'empilement externes. Si le parent gauche a z-index: 1 et que la carte droite a z-index: 2, un badge enfant avec z-index: 9999 à l'intérieur du contexte gauche n’est pas comparé directement à la carte droite. Le groupe parent reste en dessous.

Left parent context: z-index 1
└ Child badge: z-index 9999
Right card context: z-index 2

Outside, compare parent 1 and card 2.

Élever le parent gauche à z-index: 3 place son contexte entier au-dessus de la carte droite à 2. Le badge enfant conserve sa propre valeur 9999 mais devient visible dans le chevauchement. Les nombres des ancêtres et des descendants ne sont pas additionnés pour produire une valeur globale telle que 10000. Voir MDN : Contexte d'empilement.

Identifier les déclarations qui créent des contextes

Conditions représentatives Créer un nouveau contexte À vérifier
position: relative ou absolute avec z-index différent de auto Oui z-index: 0 est une valeur entière différente de auto.
position: fixed ou sticky Oui Crée un contexte même avec z-index: auto.
Élément flex ou grid avec z-index différent de auto Oui Fonctionne même avec position: static.
opacity inférieur à 1 Oui Affecte les relations de groupe ainsi que la visibilité
transform différent de none Oui Une transformation de déplacement nul diffère encore de transform: none.
isolation: isolate Oui Comment créer intentionnellement un contexte séparé

Le tableau ci-dessus est une liste des conditions fréquemment rencontrées et n'est pas une liste de toutes les conditions de création. Vous devez distinguer les cas où seul relative est spécifié et z-index est auto, et les cas où z-index : 0 est spécifié pour relative. Si le chevauchement a changé, vérifiez non seulement le nombre mais aussi les propriétés opacity ou transform nouvellement ajoutées à l'ancêtre.

Dans le même contexte, vous pouvez comparer l'avant et l'arrière en utilisant le numéro z-index de l'élément qui répond aux conditions de l'application. Cependant, comme l'ordre de rendu global du CSS comporte plusieurs niveaux, y compris les niveaux négatifs, le flux normal et les éléments positionnés, ne considérez pas auto pour tous les éléments comme égal au nombre 0 et ne calculez pas l'ordre global de la page uniquement en fonction des nombres. La pratique d'apprentissage limite les conditions aux nombres positifs et au contexte parental explicite.

Comparez les valeurs z-index du parent et de l'enfant

Enregistrez le code ci-dessous sous le nom stacking-context.html et ouvrez-le. Le badge est placé à 80-144px depuis le haut, et la carte à droite est placée dans la zone de 110-230px, avec un chevauchement vertical de 34px. Les positions gauche et droite utilisent un ratio par rapport à la largeur du parent pour maintenir le chevauchement sur mobile. Les parents et les éléments sont calculés en border-box et configurés pour éviter tout débordement inutile en dehors du conteneur.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>stacking-context.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.scene { position: relative; width: min(100%, 520px); height: 300px; background: #f1f4f7; }
 .left { position: absolute; z-index: 1; left: 0; top: 20px; width: 60%; height: 180px;
 padding: 16px; background: #ffe3b5; }
 .badge { position: absolute; z-index: 9999; left: 70%; top: 60px; width: 50%; height: 64px;
 padding: 8px; background: #f5a7cc; }
 .right { position: absolute; z-index: 2; left: 50%; top: 110px; width: 45%; height: 120px;
 padding: 12px; background: #9cd4f2; }
 .raised .left { z-index: 3; }
  </style>
</head>
<body>
<h1>Child and parent z-index values</h1><h2>Parent: 1; right card: 2</h2><div class="scene original"><div class="left">Left parent<div class="badge">Child badge<br>9999</div></div><div class="right">Right card<br>z-index: 2</div></div><h2>Parent: 3; right card: 2</h2><div class="scene raised"><div class="left">Left parent<div class="badge">Child badge<br>9999</div></div><div class="right">Right card<br>z-index: 2</div></div>
</body>
</html>

Dans la première section, le badge rose superposé est caché par la carte bleue, et dans la deuxième section, le badge rose est visible au-dessus de la carte bleue. La seule différence entre les deux zones est 1 et 3 du parent gauche. Le diagramme explicatif suivant illustre les deux états avec les mêmes coordonnées relatives ; ce n'est pas une capture d'écran du navigateur.

With a parent at z-index 1, the child badge at 9999 goes behind the neighboring card at 2; with the parent at 3, it goes in front of this card, without changing coordinates.

  1. Augmentez uniquement le z-index de .badge dans la première section à 99999. La relation entre Parent 1 et Carte 2 est maintenue, donc la partie superposée continue d'être couverte par la carte. Rétablissez le nombre à 9999.
  2. Ajoutez la règle .original .left { z-index: 3; }. Le badge montera sur la carte sans changer les coordonnées. Après confirmation, supprimez la règle ajoutée.
  3. Dans la première section originale, changez uniquement le z-index de .left en auto. Dans cet exemple, sans autres propriétés de création, le parent gauche ne crée pas de contexte séparé, donc le contexte du badge est comparé à la carte extérieure. Assurez-vous que le badge soit visible à l'avant et restaurez-le à 1.
  4. Réduisez ou élargissez l'écran pour vous assurer que le badge et la carte se chevauchent toujours. Comme les changements numériques ne sont pas visibles lorsque les coordonnées sont séparées, les comparaisons doivent être faites tout en maintenant la zone de chevauchement.

Distinguer le découpage par débordement de l'empilement

Si l'ancêtre tronque le contenu avec overflow: hidden, les parties situées en dehors de ses limites ne peuvent pas redevenir visibles simplement avec un z-index élevé. S'il est en avant dans l'ordre mais pas visible, vous devez déterminer s'il est couvert par un autre élément ou coupé à la limite d'un ancêtre. Enregistrez le code ci-dessous sous le nom stacking-clip.html et exécutez-le. Même si vous augmentez le z-index, s'il est coupé aux limites du parent, vérifiez les conditions de découpe pour overflow, retour à la ligne et points de suspension en CSS.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>stacking-clip.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.frame { position: relative; width: min(100%, 260px); height: 100px; overflow: hidden;
 border: 2px solid #789; background: #e8f5de; }
 .popup { position: absolute; z-index: 9999; left: 80%; top: 24px; width: 90px; height: 60px;
 padding: 8px; background: #f5a7cc; }
  </style>
</head>
<body>
<h1>A box that stays clipped at a higher z-index</h1><div class="frame">Parent boundary<div class="popup">Badge<br>9999</div></div><p>The right side of the badge extends beyond its parent's boundary.</p>
</body>
</html>
  1. Assurez-vous que le côté droit du badge est coupé au niveau de la bordure parente. Même si vous changez le z-index à 99999, la partie tronquée n'apparaît pas. Rétablissez le nombre à 9999.
  2. Remplacez uniquement overflow: hidden par overflow: visible dans .frame. Les autres coordonnées et nombres restent les mêmes, mais la zone en dehors de la limite est visible. Après comparaison, remettez-le en hidden.

Sur des écrans réels, supprimer l'overflow peut affecter d'autres fonctions, comme le défilement et les coins arrondis. Déterminez d'abord si la troncature est intentionnelle et, si le popup doit être en dehors des limites, déplacez la structure hors de l'ancêtre tronqué ou envisagez une méthode d'affichage séparée selon le cas. Ne changez pas l'overflow de tous les parents d'un coup juste parce que cela cache le menu.

Suivre une séquence de diagnostic

  1. Vérifiez si l’élément existe réellement et n'est pas caché en raison de display·visibility·opacity.
  2. Vérifiez les positions rectangulaires des deux éléments pour voir s'il existe une zone de superposition réelle.
  3. Remontez de l’élément cible vers ses ancêtres pour repérer les déclarations qui créent un contexte d’empilement. Identifiez le contexte parent commun dans lequel les groupes concurrents sont comparés.
  4. Déterminez si la valeur à modifier appartient au contexte de l’enfant ou à celui de son parent. Vérifiez également les éléments frères affectés et ajustez les valeurs uniquement dans la plage nécessaire.
  5. Si vous ne le voyez pas même après avoir changé l'ordre, vérifiez la troncation telle que overflow·clip et d'autres normes de coordonnées. Après avoir terminé la comparaison, les valeurs temporairement modifiées sont restaurées à leurs valeurs d'origine.

Le z-index d’un élément ordinaire ne doit pas être considéré comme un moyen de surmonter une couche d'affichage distincte, comme une boîte de dialogue placée dans la couche supérieure (top layer), en augmentant simplement le nombre. Lors du dépannage des cartes et des badges par défaut, il est important de comprendre d'abord le contexte parent réel et la troncation. Plutôt que de continuer à augmenter les nombres, vous pouvez configurer l'ordre souhaité même avec de petites valeurs en vérifiant quels groupes sont comparés.