Curso de CSS / z-index y contextos de apilamiento

El z-index controla la apilación dentro del contexto de apilamiento relevante en lugar de asignar a cada elemento una profundidad global. Un hijo con un z-index grande puede permanecer detrás de un elemento en un contexto de ancestro más alto, y el z-index no puede deshacer el recorte por overflow.

Separa la posición del orden de apilamiento

Para comparar el orden de superposición, los dos elementos deben ocupar realmente la misma área de la pantalla. Si están completamente a la izquierda y a la derecha, o arriba y abajo, cambiar el z-index no hará ninguna diferencia. Primero, comprueba la posición rectangular del elemento en las herramientas de desarrollador y determina si existen áreas superpuestas. Para identificar la referencia de coordenadas y el espacio que ocupa cada elemento, consulta position: relative, absolute, fixed y sticky.

La posición determina el estándar de coordenadas y la participación en el flujo, y el z-index determina el frente y el fondo cuando se superponen. Cambiar las coordenadas con top y cambiar el orden con z-index son tareas diferentes. El ejemplo a continuación fija las posiciones del distintivo y la tarjeta y luego cambia solo el z-index del elemento padre, para que puedas comparar las dos funciones sin mezclarlas.

z-index se puede aplicar a elementos posicionados como relative·absolute, y se puede usar para elementos Flex y Grid incluso si position: static. Si solo asignas números a bloques de flujo general ordinarios y esperas efectos, es posible que no se cumplan las condiciones de aplicación. Puedes consultar el significado del objetivo y del valor en la descripción de z-index de MDN.

Compara contextos de apilamiento como grupos

Un contexto de apilamiento agrupa a sus descendientes para comparaciones de apilamiento externas. Si el padre izquierdo tiene z-index: 1 y la tarjeta derecha tiene z-index: 2, un distintivo hijo con z-index: 9999 dentro del contexto izquierdo no compite directamente con la tarjeta derecha. El grupo padre permanece por debajo de esta.

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

Outside, compare parent 1 and card 2.

Elevar el padre izquierdo a z-index: 3 coloca todo su contexto por encima de la tarjeta derecha en 2. El distintivo hijo mantiene su propio valor de 9999 pero se vuelve visible en la superposición. Los números de ancestros y descendientes no se suman para producir un valor global como 10000. Véase MDN: Contexto de apilamiento.

Identifica declaraciones que crean contextos

Condiciones representativas Crear un nuevo contexto Qué verificar
relative o absolute + z-index distinto de auto Sí 0 también es un número y es distinto de auto.
fixed o sticky Sí Crea contexto incluso si z-index es auto
Elemento flex o grid + z-index distinto de auto Sí También con position: static
opacity menor que 1 Sí Afecta las relaciones de grupo así como la visibilidad
transform distinto de none Sí Incluso si la cantidad de movimiento es 0, es distinto de none
isolation: isolate Sí Cómo crear intencionalmente un contexto separado

La tabla anterior es una lista de condiciones que se encuentran con frecuencia y no es una lista de todas las condiciones de creación. Distingue entre los casos en los que solo se especifica relative y z-index es auto, y los casos en los que se especifica z-index: 0 para relative. Si la superposición ha cambiado, comprueba no solo el número sino también los valores de opacity o transform añadidos al ancestro.

Dentro del mismo contexto, puedes comparar el frente y el fondo usando el número de z-index del elemento que cumple con las condiciones de la aplicación. Sin embargo, debido a que el orden general de dibujo de CSS tiene múltiples niveles, incluyendo niveles negativos, flujo normal y elementos posicionados, no trates a auto para todos los elementos como igual a 0 ni calcules el orden general de la página basándote únicamente en los números. La práctica de aprendizaje restringe las condiciones a números positivos y un contexto de padre explícito.

Compara los valores de z-index del padre y del hijo

Guarda el código abajo como stacking-context.html y ábrelo. La insignia se coloca a 80-144px desde la parte superior, y la tarjeta en la derecha se coloca en el área de 110-230px, con una superposición vertical de 34px. Las posiciones izquierda y derecha usan una proporción respecto al ancho del contenedor para mantener la superposición en móviles. Los padres y elementos se calculan como border-box y se configuran para prevenir desbordamiento innecesario fuera del contenedor.

<!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>

En la primera sección, la insignia rosa superpuesta está oculta por la tarjeta azul, y en la segunda sección, la insignia rosa es visible encima de la tarjeta azul. La única diferencia entre las dos zonas es 1 y 3 del padre izquierdo. El siguiente diagrama explicativo ilustra los dos estados con las mismas coordenadas relativas; no es una captura de pantalla del navegador.

With the parent at z-index 1, the child at 9999 ends up behind the neighboring card at 2. By raising the parent to 3, the child appears in front without changing coordinates.

  1. Aumenta únicamente el número .badge en la primera sección a 99999. Se mantiene la relación entre el Padre 1 y la Tarjeta 2, por lo que la parte superpuesta continúa estando cubierta por la tarjeta. Restaura el número a 9999.
  2. Añade la regla .original .left { z-index: 3; }. La insignia aparecerá por delante de la tarjeta sin cambiar las coordenadas. Después de la confirmación, elimina la regla añadida.
  3. En la primera sección original, solo cambia el z-index de .left a auto. En este ejemplo, sin otras propiedades de creación, el padre izquierdo no crea un contexto separado, por lo que el contexto de la insignia se compara con la tarjeta externa. Asegúrate de que la insignia sea visible al frente y restaura el z-index de .left a 1.
  4. Ajusta la pantalla hacia más estrecha o más ancha para asegurarte de que la insignia y la tarjeta todavía se superpongan. Dado que los cambios numéricos no son visibles cuando las coordenadas están separadas, las comparaciones deben hacerse manteniendo el área de superposición.

Distingue el recorte por desbordamiento del apilamiento

Si el ancestro trunca el contenido con overflow: hidden, las partes fuera de sus límites no se pueden hacer visibles nuevamente solo con un z-index alto. Si tiene un orden superior pero no es visible, necesitas determinar si está cubierto por otro elemento o truncado en el límite de un ancestro. Guarda el siguiente código como stacking-clip.html y ejecútalo. Incluso si aumentas el z-index, si está truncado en el límite del padre, revisa las condiciones de corte para overflow, saltos de texto y puntos suspensivos con 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. Asegúrate de que el lado derecho de la insignia esté recortado en el borde del contenedor padre. Incluso si cambias el z-index a 99999, la parte truncada no aparece. Restaura el número a 9999.
  2. Cambia solo el overflow del .frame a visible. Las demás coordenadas y números permanecen iguales, pero el área fuera del límite es visible. Después de la comparación, devuélvelo a hidden.

En pantallas reales, eliminar el overflow puede afectar otros propósitos, como el desplazamiento y las esquinas redondeadas. Primero determina si la truncación es intencionada y, si el popup debe estar fuera de los límites, mueve la estructura fuera del ancestro con truncado o considera un método de visualización separado según sea apropiado. No cambies el overflow de todos los padres a la vez solo porque oculta el menú.

Sigue una secuencia de diagnóstico

  1. Verifica si el elemento realmente existe y no está oculto debido a display·visibility·opacity.
  2. Comprueba las posiciones rectangulares de los dos elementos para ver si hay un área de superposición real.
  3. Sube desde el elemento objetivo y sus ancestros para encontrar declaraciones que creen un contexto de apilamiento. Determina cuál es el padre común con el que se comparan los contextos en competencia.
  4. Determina si debes cambiar el z-index del hijo o el del contexto padre. También verifica los elementos hermanos afectados y ajusta los valores solo dentro del rango necesario.
  5. Si no lo ves incluso después de cambiar el orden, verifica el recorte causado por overflow y otras propiedades de recorte y otros estándares de coordenadas. Después de completar la comparación, los valores modificados temporalmente se restauran a sus valores originales.

No se debe pensar que el z-index de un elemento regular es un medio para superar una capa de visualización separada, como un diálogo en la capa superior, simplemente aumentando el número. Al solucionar problemas con tarjetas y distintivos predeterminados, es importante primero comprender el contexto real del elemento padre y la truncación. En lugar de seguir aumentando los números, puedes configurar el orden deseado incluso con valores pequeños verificando qué grupos se comparan.