La propiedad z-index en CSS se utiliza para ordenar los elementos que se superpongan entre sí. Con la propiedad z-index podemos controlar qué elemento iría encima y cual debajo, como si el documento tuviera profundidad, tres dimensiones en lugar de dos.

z-index CSS
z-index CSS Nick Babich: Top Design Moments for Mobile App

Puede haber muchos motivos para que dos elementos se superpongan. Por ejemplo, ¿quién no se ha visto lidiando con elementos posicionados de forma absoluta y fija que se superponen con otros?

El orden z predeterminado

Antes de ver cómo utilizar z-index, vamos a repasar como se determina el orden z de elementos superpuestos.

El valor predeterminado de z-index es auto. El navegador irá ordenando los elementos en el orden en el que aparezcan, el primero quedará abajo y los siguientes elementos se irán apilando encima. Esta regla la aplica en este orden:

  1. Primero posiciona el elemento raíz <html>
  2. Luego los elementos no posicionados (cualquiera con el valor predeterminado position: static)
  3. Luego los elementos posicionados (cualquiera con position: relative, position: absolute, position: fixed, position: sticky, o cualquier otro valor diferente a position: static).

Si al terminar este post tenéis más curiosidad, podéis ampliar leyendo el caso de los elementos flotados.

Ejemplo

Vamos a ver como los elementos no posicionados son colocados primero aunque aparezcan los últimos en el HTML:

<style>
    .azul, .rojo, .verde {
        position: absolute;
    }
</style>
<div class="rojo">
    <div class="verde"></div>
</div>
<div class="gris"></div>
<div class="azul"></div>

El orden de apilamiento automático daría lugar al siguiente resultado:

Stacking predeterminado
Stacking predeterminado

Como ves, dejando los valores z-index en su valor predeterminado (z-index: auto), los elementos no posicionados se colocan siempre primero y después irán todos los demás.

Cómo utilizar z-index

Con la propiedad z-index podemos cambiar el orden predeterminado que hemos visto antes. Simplemente se especifica el número de orden: z-index: 1, z-index: 2, etc. También puede tomar valores negativos: z-index: -1, z-index: -2, etc.

A mayor valor más arriba se representará el elemento. Si dos elementos tienen el mismo valor, el que sea definido antes se colocará primero.

Pero hay que tener dos cosas muy claras:

  • La propiedad z-index solo se aplica a elementos posicionados. Los elementos no posicionados siempre se van a colocar uno en encima de otro en el orden en el que aparecen en el código.
  • La propiedad z-index no es heredable.
  • Definir la propiedad z-index con un valor diferente a auto crea un stacking context, un contexto de apilamiento. También se crea un stacking context en todos los elementos con position: fixed o sticky. Luego veremos qué significa esto.

Ejemplo

Si ahora cambiamos el CSS anterior por este:

.gris, .rojo, .verde {
    position: absolute;
}
.gris {
    z-index: 2;
}
.verde {
    z-index: 3;
}
.azul {
    z-index: 100; // Sin efecto, es un elemento no-posicionado.
}

Obtendremos este resultado:

Ejemplo de z-index
El elemento verde se ha posicionado en lo más alto de eje z

Como se puede ver, los elementos posicionados para los que se ha definido un z-index (el verde y el gris) se ordenan uno sobre otro sin importar que el elemento verde sea descendiente de otro elemento. Se dice que ambos elementos se ordenan en el mismo contexto de apilamiento, en el mismo stacking context.

Como se mencionó antes, el stacking context se crea en todos los elementos posicionados fixed o sticky, y en los posicionados con relative y absolute que además tengan un z-index diferente a auto. Y ese es nuestro caso, el elemento rojo está posicionado en absolute pero no tiene z-index, por tanto, este elemento no crea un nuevo contexto de apilamiento y su elemento hijo (el verde) se ordena en el contexto superior, que en este caso es el mismo contexto que el elemento gris.

Vamos a ver como se puede crear un nuevo stacking context. Imaginemos que introducimos un elemento más:

<div class="rojo">
    <div class="verde"></div>
</div>
<div class="gris"></div>
<div class="amarillo"></div>
<div class="azul"></div>

Y le aplicamos este CSS:

.gris, .rojo, .verde, .amarillo {
    position: absolute;
}
.amarillo {
    z-index: 0;
}
.rojo {
    z-index: 1;
}
.gris {
    z-index: 2;
}
.verde {
    z-index: 3;
}
.azul {
    z-index: 100; // Sin efecto, elemento no posicionado
}
Stacking context
Se ha creado un nuevo contexto de apilamiento en el elemento rosa

Observa el resultado. De todos los elementos posicionados, el amarillo tiene el z-index más bajo y aparece debajo, luego aparece el rojo, hasta aquí bien. Pero fíjate como el verde ya no se superpone al gris aunque el z-index del elemento verde sea mayor.

Antes, el elemento verde y el gris se ordenaban en el mismo contexto de apilamiento, pero ahora, el elemento rojo ha creado un nuevo contexto de apilamiento, pues cumple dos reglas: es un elemento posicionado con absolute y tiene un z-index diferente de auto.

Así que el z-index del elemento verde ahora se aplica al contexto de apilamiento creado por su elemento contenedor.

El stacking context se crea en otras muchas más situaciones, tantas que cuesta recordarlas todas, entre las más habituales:

  • Elemento raíz del documento
  • Elementos position: absolute y position: relative con un valor z-index diferente de auto
  • Elementos position: fixed y position: sticky
  • Elementos con opacity menor a 1
  • Elemento dentro de un contenedor flex y un valor z-index diferente de auto.

Referencias

  1. Entendiendo la propiedad CSS z-index. MDN web docs.
  2. CSS 2.2: Layered presentation. Specifying the stack level: the z-index property. W3C
  3. Veronika Ivhed. (19 Mayor 2018) Z-Index Explained: How to Stack Elements Using CSS. FreeCodeCamp.