El eje que no se ve
Además de ancho y alto, las cajas viven en un tercer eje: el eje Z, que va de
la pantalla hacia ti. Es la profundidad. Cuando dos elementos se solapan,
z-index decide cuál queda por delante: a mayor número, más cerca de ti.
Piensa en una baraja de cartas sobre la mesa: la de arriba tapa a las de abajo.
.atras { position: absolute; z-index: 1; }
.delante { position: absolute; z-index: 2; } /* tapa a .atras */
z-index solo funciona con position
z-index solo tiene efecto en elementos posicionados (es decir, con
position distinto de static: relative, absolute, fixed o
sticky). En un elemento static se ignora por completo.
⚠️ TRAMPA CLÁSICA: poner z-index y olvidar el position. Subes el
número a 9999, no pasa nada, y empiezas a dudar de tu cordura. Antes de tocar el
z-index, asegúrate de que el elemento esté posicionado.
.modal {
position: fixed; /* sin esto, el z-index no haría nada */
z-index: 100;
}
Contextos de apilamiento (intro)
Un contexto de apilamiento es una "burbuja" Z independiente. Dentro de ella,
los z-index de los hijos solo compiten entre sí, no con elementos de
fuera. Un elemento crea un contexto nuevo cuando, por ejemplo:
- tiene
positionposicionado y unz-indexnumérico, o - tiene
opacitymenor que 1, unatransform, unfilter, etc.
La consecuencia práctica: un hijo con z-index: 9999 nunca superará a un
elemento de otra burbuja cuyo padre tenga un z-index mayor. Si un modal
"se esconde" detrás de algo pese a su z-index enorme, casi siempre la causa
es un contexto de apilamiento creado por un ancestro.
Idea clave: el orden Z se resuelve por niveles, primero entre burbujas y luego dentro de cada una. Mantén pocos contextos y números bajos y ordenados; tu yo del futuro te lo agradecerá.
Con esto cierras el bloque de colocación clásica. El siguiente paso es flexbox, donde dejas de empujar cajas una a una y le dices al contenedor que las reparta por ti.
Ejemplos
El círculo rojo queda por delante por su z-index mayor
<style>
.zona { position: relative; height: 80px; }
.circulo {
position: absolute;
top: 10px;
width: 50px;
height: 50px;
border-radius: 50%;
}
.azul { left: 10px; background: #3b82f6; z-index: 1; }
.rojo { left: 35px; background: #ef4444; z-index: 2; }
</style>
<div class="zona">
<div class="circulo azul"></div>
<div class="circulo rojo"></div>
</div>