z-index dropdown menú: problemas y soluciones
El clásico: Tienes un menú desplegable que debería aparecer encima de todo, pero aparece detrás de las tarjetas de tu contenido. 📦
Aquí tienes la solución.
¿Por qué el dropdown queda atrás?
El problema común
<nav class="navbar" style="z-index: 10">
<div class="menu-container">
<button>Menú</button>
<div class="dropdown">
<!-- Este dropdown NO puede salir del navbar -->
Opciones...
</div>
</div>
</nav>
<main style="z-index: 1">
<!-- Las tarjetas están aquí -->
<div class="card">Producto 1</div>
<div class="card">Producto 2</div>
</main>
El problema: El dropdown está limitado por el z-index: 10 del navbar.
Soluciones probadas
Solución 1: Sube el z-index del padre
La solución más simple:
.navbar {
position: relative;
z-index: 1000; /* Suficientemente alto */
}
.dropdown {
position: absolute;
z-index: 1001; /* Más alto que el navbar */
}
Solución 2: Usa position: fixed para el dropdown
Si el menú debe estar siempre encima:
.dropdown {
position: fixed;
z-index: 9999;
top: 100%;
left: 0;
}
Precaución: Esto puede causar problemas con scroll en páginas largas.
Solución 3: Mueve el dropdown fuera del flujo
Usa un portal para renderizar el dropdown en document.body:
React:
import { createPortal } from 'react-dom';
function Dropdown({ isOpen, children }) {
if (!isOpen) return null;
return createPortal(
<div className="dropdown">{children}</div>,
document.body
);
}
Vanilla JS:
// Mover el dropdown a body cuando se abre
document.querySelector('.dropdown').appendChild(document.body);
Solución 4: Evita overflow: hidden en contenedores
/* ❌ Este corta el dropdown */
.menu-container {
overflow: hidden;
}
/* ✅ Usa overflow: auto o visible */
.menu-container {
overflow: visible;
}
Ejemplo completo: Navbar con dropdown
.navbar {
position: relative;
z-index: 100;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.menu-trigger {
position: relative;
padding: 0.5rem 1rem;
cursor: pointer;
}
.dropdown-menu {
position: absolute;
z-index: 200; /* Mayor que el navbar */
top: 100%;
left: 0;
min-width: 200px;
background: white;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
border-radius: 4px;
}
/* Si hay contenido que lo supera */
.main-content {
/* No pongas z-index aquí */
}
<nav class="navbar">
<div class="menu-trigger">
Menú
<div class="dropdown-menu">
<a href="#">Opción 1</a>
<a href="#">Opción 2</a>
<a href="#">Opción 3</a>
</div>
</div>
</nav>
<main class="main-content">
<!-- Las tarjetas pasan DETRÁS del dropdown -->
<div class="card">Producto</div>
</main>
Problema: Sticky header + Dropdown
Si tienes un header sticky:
.sticky-header {
position: sticky;
z-index: 100;
}
.dropdown {
z-index: 200; /* Debe ser mayor que el header */
}
Checklist para dropdowns
- ¿El navbar/header tiene z-index?
- ¿El dropdown tiene mayor z-index que su padre?
- ¿Hay
overflow: hiddencortando el dropdown? - ¿Usaste
position: fixedsi es necesario?
Artículos relacionados
- Problemas z-index CSS: Guía completa
- z-index no funciona: 5 soluciones
- Stacking context explicado
- z-index modal no funciona
- z-index con overflow:hidden
: El dropdown necesita espacio para respirar. Dale el z-index que merece.