z-index e Contexto de Empilhamento no CSS | Web Academy
Até agora, tratamos o navegador como uma superfície bidimensional composta pelo eixo horizontal X (largura) e pelo eixo vertical Y (altura). No entanto, no momento em que usamos coordenadas de posicionamento, caixas inevitavelmente colidem e se sobrepõem. É aqui que entra o Eixo Z: a terceira dimensão perpendicular à tela, apontando diretamente para os olhos do usuário. Controlar qual elemento fica na frente ou atrás não é uma questão de sorte nem de quem tem o maior número arbitrário no z-index, mas sim de entender a mecânica dos Contextos de Empilhamento (Stacking Contexts).
📑 Índice do Conteúdo
1. A Ordem Natural de Pintura (Antes de Usar z-index)
Antes de aplicarmos qualquer linha de z-index, o navegador já possui uma hierarquia rígida de 7 camadas para desenhar os pixels na tela. Quando dois elementos colidem sem z-index declarado, o motor gráfico segue esta sequência de trás para a frente (do mais profundo para o mais superficial):
| Nível | Tipo de Elemento / Conteúdo | Comportamento no Eixo Z |
|---|---|---|
| 1 (Fundo) | Background e Bordas do Elemento Raiz | A tela em branco do navegador (<html>). |
| 2 | Elementos Não-Posicionados em Bloco | <div>, <section>, <p> no fluxo normal (ordem do HTML). |
| 3 | Elementos Flutuantes (Floats) | Caixas com float: left ou float: right. |
| 4 | Elementos em Linha (Inline e Texto) | Textos, <span>, <strong>, imagens no fluxo normal. |
| 5 (Frente) | Elementos Posicionados | Qualquer caixa com position diferente de static (ordem de aparição no HTML). |
Revelação Surpreendente: Apenas declarar position: relative em uma caixa — mesmo sem alterar coordenadas nem definir z-index — já a joga automaticamente para a frente de todos os blocos, floats e textos normais da página!
2. Como Funciona a Propriedade z-index
A propriedade z-index aceita números inteiros positivos, negativos ou zero. Quanto maior o valor, mais próximo da tela do usuário o elemento se posiciona:
.camada-fundo {
position: relative;
z-index: 1;
}
.camada-frente {
position: relative;
z-index: 10; /* Fica visivelmente por cima da camada-fundo */
}
.marca-dagua-recuada {
position: absolute;
z-index: -1; /* Fica atrás do próprio texto do seu contêiner */
}
A Regra de Ouro do z-index: A propriedade z-index NÃO FUNCIONA em elementos com position: static comum. Para que o z-index tenha efeito, o elemento precisa:
- Possuir posicionamento explícito:
relative,absolute,fixedousticky; OU - Ser um item filho direto de um contêiner Flexbox (
display: flex) ou CSS Grid (display: grid), onde o CSS moderno permitez-indexmesmo sem declararposition!
3. O Mito do z-index: 999999 e os Contextos de Empilhamento
Todo desenvolvedor já viveu esse pesadelo: você precisa que um menu dropdown ou modal fique na frente de outro cartão. Você aplica z-index: 10. Não funciona. Você tenta z-index: 999. Nada. Em desespero, você escreve z-index: 99999999 !important; e o elemento continua teimosamente atrás do outro componente!
Por que isso acontece? Porque o z-index não é um valor global absoluto. Ele é relativo ao seu Contexto de Empilhamento (Stacking Context) local.
A Metáfora dos Andares do Prédio
Pense no Stacking Context como prédios de apartamentos:
- O Prédio A tem uma altura no térreo (
z-index: 1). - O Prédio B tem uma base elevada (
z-index: 2). - Se você subir na cobertura do Prédio A (andar
z-index: 999999), você nunca estará acima de alguém que está no saguão do Prédio B (z-index: 2), porque a base de B é superior à base de A!
<!-- Exemplo da Armadilha Clássica -->
<div class="card-a" style="position: relative; z-index: 1;">
<!-- Este tooltip NUNCA conseguirá ficar na frente do card-b! -->
<div class="tooltip" style="position: absolute; z-index: 999999;">
Tooltip Preso no Teto do Pai
</div>
</div>
<div class="card-b" style="position: relative; z-index: 2;">
<p>Conteúdo do Card B (Vence tudo dentro do Card A)</p>
</div>
4. Os 7 Gatilhos que Criam Novos Contextos de Empilhamento
Um novo Contexto de Empilhamento é gerado no navegador sempre que um elemento atende a qualquer uma das seguintes condições:
- O elemento raiz do documento (
<html>). - Qualquer elemento posicionado (
relativeouabsolute) cujoz-indexseja diferente deauto(ex.:z-index: 0já cria um novo contexto!). - Qualquer elemento com
position: fixedouposition: sticky. - Itens flex ou grid cujo
z-indexseja diferente deauto. - Elementos com opacidade reduzida:
opacity < 1. - Elementos com transformações ou filtros gráficos:
transform,filter,perspective,clip-pathoumaskdiferentes denone. - Elementos com
isolation: isolate.
5. A Arma Secreta do CSS Moderno: isolation: isolate
No passado, para criar um contexto de empilhamento isolado em um componente (evitando que seus elementos internos colidissem com o restante do site), os programadores recorriam a “hacks” como position: relative; z-index: 0; ou transform: translateZ(0);.
O CSS moderno introduziu a propriedade isolation: isolate especificamente para resolver esse problema com elegância cirúrgica:
.card-componente {
/* Cria uma fronteira de empilhamento local estrita */
/* Nada de z-index interno vazará para o resto da página! */
isolation: isolate;
}
Com isolation: isolate, você pode usar z-index: -1 dentro do card para colocar uma imagem decorativa atrás do texto, sem o risco da imagem afundar para trás do fundo da página inteira!
6. Arquitetura Profissional: Tokens de Camadas no Design System
Para exterminar para sempre a “guerra de z-index” nos seus projetos corporativos, nunca escreva números mágicos dispersos pelo CSS. Padronize uma escala com variáveis CSS no seu :root:
:root {
/* Escala Semântica de Camadas Z-Index */
--z-abaixo: -1; /* Decorações atrás do fluxo */
--z-padrao: 1; /* Conteúdo básico elevado */
--z-dropdown: 100; /* Menus suspensos e selects */
--z-sticky: 200; /* Barras de navegação fixas */
--z-overlay: 500; /* Máscaras escuras de fundo */
--z-modal: 510; /* Janelas modais e diálogos */
--z-popover: 800; /* Tooltips e balões explicativos */
--z-toast: 1000; /* Alertas e notificações críticas */
}
/* Aplicação Limpa e Autoexplicativa */
.menu-dropdown {
position: absolute;
z-index: var(--z-dropdown);
}
.janela-modal {
position: fixed;
z-index: var(--z-modal);
}
7. Laboratório Prático: O Fenômeno do Contexto de Empilhamento
No código abaixo, experimente observar como o Card 1 (com z-index: 1) não consegue colocar seu distintivo à frente do Card 2 (com z-index: 2), e como o uso de isolation: isolate organiza os planos de profundidade:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Laboratório de Camadas z-index</title>
<style>
body {
font-family: 'Inter', system-ui, sans-serif;
background: #0f172a;
color: #f8fafc;
padding: 40px;
}
.painel-demonstracao {
position: relative;
width: 480px;
height: 260px;
background: #1e293b;
border: 1px solid #334155;
border-radius: 16px;
padding: 20px;
}
/* Card 1 - Nível Base 1 */
.card-1 {
position: absolute;
top: 30px;
left: 30px;
width: 240px;
padding: 20px;
background: #3b82f6;
border-radius: 10px;
z-index: 1; /* Cria um Stacking Context de nível 1 */
}
/* Distintivo de z-index gigante dentro do Card 1 */
.badge-insana {
position: absolute;
bottom: -15px;
right: -30px;
background: #ef4444;
color: #fff;
padding: 8px 16px;
border-radius: 9999px;
font-weight: 800;
font-size: 0.75rem;
z-index: 99999; /* INÚTIL: Preso ao teto z-index: 1 do pai! */
box-shadow: 0 4px 12px rgba(0,0,0,0.5);
}
/* Card 2 - Nível Base 2 */
.card-2 {
position: absolute;
top: 80px;
left: 140px;
width: 240px;
padding: 20px;
background: #10b981;
border-radius: 10px;
z-index: 2; /* Vence o Card 1 E a badge de 99999! */
box-shadow: 0 10px 25px rgba(0,0,0,0.4);
}
</style>
</head>
<body>
<h2>Por que z-index: 99999 Perde para z-index: 2?</h2>
<div class="painel-demonstracao">
<div class="card-1">
<h4 style="margin:0;">Card 1 (z-index: 1)</h4>
<div class="badge-insana">z-index: 99999</div>
</div>
<div class="card-2">
<h4 style="margin:0;">Card 2 (z-index: 2)</h4>
<p style="font-size:0.85rem; margin-bottom:0;">
Observe que eu fico por cima da badge vermelha, embora meu z-index seja apenas 2!
</p>
</div>
</div>
</body>
</html>
Teste esse exemplo interativo no Playground IDE, experimente inverter os z-index dos pais ou aplicar isolation: isolate para comprovar o comportamento gráfico na prática:
8. Resumo e Próximos Passos
z-indexcontrola a posição no eixo Z (profundidade perpendicular à tela).- Elementos posicionados (
relative,absolute, etc.) ficam naturalmente à frente do fluxo normal antes de qualquerz-indexser digitado. z-indexnão funciona em caixas estáticas normais; exige posicionamento ou ser filho direto de Flex/Grid.- Valores astronômicos como
z-index: 999999falham quando o elemento pai está em um Contexto de Empilhamento inferior. - A propriedade moderna
isolation: isolatecria uma fronteira limpa e estrita de camadas sem efeitos colaterais visuais.
Próximo Passo: Agora que você domina as coordenadas e o empilhamento em camadas, o que acontece quando o conteúdo de uma caixa é maior do que o tamanho delimitado para ela? Na Lição 25, dominaremos Overflow & Controle de Rolagem no CSS (visible, hidden, scroll, auto e clip)!