Problemas con z-index CSS: Guía completa de soluciones

¿Alguna vez has puesto z-index: 9999 y aun así tu elemento aparece detrás de otro? 😵 Tranquilo, no estás solo. Los problemas con z-index son uno de los quebraderos de cabeza más comunes en CSS.

La buena noticia: una vez que entiendes el contexto de apilamiento (stacking context), puedes resolver cualquier problema de z-index.


¿Por qué tu z-index no funciona?

Antes de ver las soluciones, necesitas entender por qué falla. El error más común es pensar que z-index: 9999 garantiza que tu elemento estará encima de todo.

Pero eso no es cierto.

El problema está en el contexto de apilamiento. Cada elemento crea su propio contexto, y los elementos hijos solo pueden posicionarse dentro de ese contexto.


Las 5 causas principales de problemas con z-index

1. El elemento no tiene position definida

z-index solo funciona en elementos con position distinto de static.

/* ❌ NO funciona - falta position */
.boton {
  z-index: 100;
}

/* ✅ CORRECTO */
.boton {
  position: relative;
  z-index: 100;
}

2. El elemento padre tiene un z-index bajo

Si el padre de tu elemento tiene un z-index bajo, ningún hijo puede salir de ese contexto, aunque tenga un z-index más alto.

.padre {
  position: relative;
  z-index: 1; /* El hijo nunca podrá estar encima del hermano del padre */
}

.hijo {
  position: absolute;
  z-index: 9999; /* ¡No funciona! Está limitado por el padre */
}

3. Propiedades que crean nuevo contexto de apilamiento

Algunas propiedades crean un nuevo contexto de apilamiento automáticamente:

  • opacity menor a 1
  • transform (excepto none)
  • filter
  • isolation: isolate
  • position: fixed
  • Elementos dentro de flex containers con z-index
/* Este div crea un nuevo stacking context */
.caja-efecto {
  opacity: 0.9; /* Nuevo contexto - hijos limitados */
  transform: translateX(10px); /* También crea nuevo contexto */
}

4. Conflictos con position: fixed

Los elementos con position: fixed crean su propio contexto de apilamiento, y pueden causar conflictos con modals y overlays.

5. Overflow: hidden en el padre

Cuando el padre tiene overflow: hidden, puede cortar elementos posicionados que deberían verse.


Soluciones definitivas para problemas de z-index

Solución 1: Saca al hijo del contexto del padre

El truco más efectivo es sacar al elemento del flujo del padre usando un portal o moviendo el HTML:

// React: Portal para romper stacking context
import { createPortal } from 'react-dom';

return createPortal(
  <Modal>{contenido}</Modal>,
  document.body // Se renderiza fuera del padre
);

Solución 2: Usa position: fixed para elementos críticos

Para modales y overlays, usa position: fixed en lugar de absolute:

.modal {
  position: fixed; /* Crea stacking context independiente */
  z-index: 9999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Solución 3: Remueve propiedades que crean nuevo contexto

Si el problema es opacity o transform, considera alternativas:

/* ❌ Crea nuevo stacking context */
.caja {
  opacity: 0.5;
}

/* ✅ Usa alternativas */
.caja {
  background: rgba(255, 255, 255, 0.5); /* Color con transparencia */
}

Solución 4: Establece el contexto correcto

A veces solo necesitas que el padre tenga el z-index correcto:

.header {
  position: relative;
  z-index: 100;
}

.menu-desplegable {
  position: absolute;
  z-index: 200; /* Ahora funciona porque el padre tiene z-index */
}

Solución 5: Usa isolation: isolate

Esta propiedad CSS crea un nuevo stacking context sin efectos secundarios:

.componente-aislado {
  isolation: isolate;
  /* Ahora los hijos están aislados */
}

Errores comunes con z-index

❌ z-index: 999999

Poner números excesivamente altos no ayuda. Usa una escala lógica:

/* ❌ Números absurdos */
.modal { z-index: 999999; }

/* ✅ Escala razonable */
.dropdown    { z-index: 10; }
.sticky-nav   { z-index: 100; }
.modal        { z-index: 1000; }
.toast        { z-index: 2000; }

❌ Ignorar el orden de apilamiento por defecto

El navegador apila elementos en orden específico incluso sin z-index:

  1. Elementos con position: static (fondo de la página)
  2. Elementos flotantes
  3. Elementos con position: static en línea
  4. Elementos posicionados (es aquí donde entra z-index)

❌ Mezclar unidades de z-index

Todos los elementos deberían usar la misma escala para evitar confusiones.


Guía paso a paso para debuggear z-index

  1. Verifica que tenga position: Asegúrate de que el elemento tenga position: relative, absolute, fixed o sticky.

  2. Inspecciona el padre: El padre puede estar limitando el z-index del hijo.

  3. Busca propiedades problemáticas: Revisa opacity, transform, filter en los padres.

  4. Usa DevTools: En Chrome, activa “Layer” en DevTools para visualizar las capas.

  5. Prueba con valores extremos: Si z-index: 1 no funciona, el problema no es el valor.


Artículos relacionados


Conclusión

Los problemas de z-index casi siempre se reducen a entender el stacking context. Una vez que comprendes que los hijos están limitados por el contexto de sus padres, todo tiene sentido.

** (Recuerda):** Un alto z-index no garantiza estar encima si el padre tiene un contexto de apilamiento lower.

¿Tienes un problema específico con z-index? Deja tu pregunta en los comentarios.