Qué hace z-index
Cuando los elementos se superponen, z-index decide cuál se dibuja delante. Gana el número mayor. Funciona en elementos posicionados (cualquier position excepto static) y en elementos flex y grid:
Sin z-index, los elementos que aparecen después en el HTML se dibujan encima de los anteriores, así que C taparía a B y B taparía a A. Los valores de z-index invierten eso: A queda delante, luego C y luego B.
Los valores
| Valor | Significado |
|---|---|
auto (por defecto) | Se apila en el nivel 0 con sus hermanos y no crea un contexto de apilamiento |
0 | Nivel 0, pero crea un contexto de apilamiento |
| Entero positivo | Delante de los valores menores |
| Entero negativo | Detrás del nivel 0, y detrás del contenido del padre si el padre forma el contexto de apilamiento |
Solo los enteros son válidos: z-index: 1.5 se ignora.
Por qué un z-index de 9999 puede perder: los contextos de apilamiento
Los valores de z-index no se comparan en toda la página. Los elementos se agrupan en contextos de apilamiento, y un z-index solo ordena elementos dentro del mismo contexto. Luego el contexto se coloca como una sola capa, con el z-index del elemento que lo creó.
Abajo, el menú desplegable azul tiene z-index: 9999, pero vive dentro de un encabezado con z-index: 1. El banner verde, hermano de ese encabezado, tiene z-index: 2. Toda la capa del encabezado, menú incluido, queda debajo del banner:
Presiona el botón. Con z-index: auto el encabezado ya no forma un contexto de apilamiento, así que el 9999 del menú se compara directamente con el 2 del banner, y el menú pasa al frente. Subir el menú a 99999 nunca habría servido.
Qué crea un contexto de apilamiento
Cualquiera de estas propiedades convierte a un elemento en su propio contexto de apilamiento y atrapa el z-index de todo lo que contiene:
| Propiedad | Condición |
|---|---|
position: relative o absolute | Con un z-index distinto de auto |
position: fixed o sticky | Siempre |
| Elemento flex o grid | Con un z-index distinto de auto |
opacity | Menor que 1 |
transform, scale, rotate, translate | Cualquier valor distinto de none |
filter, backdrop-filter | Cualquier valor distinto de none |
isolation | isolate |
mix-blend-mode | Cualquier valor distinto de normal |
will-change | Si nombra alguna de las propiedades de arriba |
contain | layout o paint (y strict, content) |
Las que sorprenden son opacity y transform: agregar un desvanecido o una animación de hover a un padre puede mandar de repente su menú desplegable detrás de la sección siguiente.
El z-index: 10 del tooltip debería ponerlo por encima de la columna siguiente. Pero opacity: 0.99 hace que la primera columna sea un contexto de apilamiento con z-index auto (nivel 0), y la segunda columna aparece después en el HTML en el mismo nivel, así que se pinta encima de toda la primera columna, tooltip incluido. Borra la línea de opacity y el tooltip vuelve a quedar delante.
z-index negativo
Un z-index negativo pone un elemento detrás de sus hermanos. Si el padre no forma un contexto de apilamiento, puede quedar incluso detrás del fondo del padre, lo que suele sorprender. isolation: isolate en el padre crea un contexto sin ningún otro efecto visual y mantiene dentro al hijo negativo:
Sin isolation, el marco ámbar cae detrás del propio fondo gris del botón, así que solo se ve su borde. Con isolation: isolate, el marco se queda dentro del contexto de apilamiento del botón: por encima de su fondo y por debajo de su texto.
Una escala de z-index
Elige unas pocas capas con nombre para todo el sitio en lugar de subir números sin fin:
: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 mayoría de los problemas de capas son problemas de contextos de apilamiento, no de números, así que una escala pequeña más isolation: isolate en los componentes que usan z-index por dentro resuelve mucho. z-index necesita posicionamiento para funcionar; la página de position lo explica.
Errores comunes
- z-index en un elemento static. Agrega
position: relative(o haz que sea un elemento flex o grid). - Subir hasta 9999. Si un padre forma un contexto de apilamiento por debajo del rival, ningún valor del hijo puede ganar. Busca el contexto.
- Un
opacity,transformofilternuevo en un padre que de repente atrapa su menú desplegable. - Valores decimales.
z-index: 1.5es inválido. - Esperar que
z-index: 0yautose comporten igual.0crea un contexto de apilamiento;autono. - Modales dentro de componentes muy anidados. Renderízalos cerca del final de
<body>(o usa la capa superior del elemento<dialog>), para que ningún contexto ancestro pueda atraparlos.
Preguntas frecuentes
¿Qué hace z-index?
Define el orden de apilamiento de los elementos que se superponen: un valor mayor se dibuja delante de uno menor dentro del mismo contexto de apilamiento. El valor por defecto es auto, y los valores son números enteros, incluidos los negativos.
¿Por qué no funciona mi z-index?
O el elemento no está posicionado (z-index necesita un position distinto de static, o ser hijo de un flex o grid), o está dentro de un padre que forma un contexto de apilamiento con un orden más bajo. Un hijo nunca puede subir por encima de un elemento que está por encima de su contexto de apilamiento, tenga el z-index que tenga.
¿Qué es un contexto de apilamiento?
Un grupo de elementos que se apilan juntos como una sola capa. Dentro de él, los hijos se ordenan por su z-index; hacia afuera, el grupo entero se coloca según el z-index del elemento que lo creó.
¿Qué crea un contexto de apilamiento?
Entre otros: el elemento raíz, un elemento posicionado con un z-index distinto de auto, position: fixed o sticky, un hijo flex o grid con z-index, opacity menor que 1, transform, filter, isolation: isolate y will-change sobre esas propiedades.
¿z-index funciona sin position?
No en elementos block o inline normales: position: static lo ignora. Sí funciona en elementos flex y elementos grid sin ningún position.