Z-Index sem guerra: padrões, tokens e QA para camadas previsíveis
z-index não é um jogo de números — é um contrato entre design, engenharia e QA. Quando times sobem valores aleatoriamente até chegar em 99999, o resultado são bugs intermitentes, correções que quebram outras telas e uma base de código onde ninguém sabe mais qual camada deveria ficar por cima. A solução é tratar z-index como token de design: faixas reservadas por tipo de componente, nomes semânticos e um ponto único de edição.
Este artigo cobre o ciclo completo — diagnóstico de stacking context, escala de tokens, implementação em CSS e Tailwind, ferramentas de inspeção e um plano de QA para validar cobertura de camadas sem depender de "olhômetro".
O que realmente quebra o empilhamento: stacking context na prática
O z-index quase nunca falha sozinho. O que falha é o entendimento dos stacking contexts. O z-index só é comparável entre elementos no mesmo contexto. Se um elemento pai cria um novo contexto, os filhos ficam presos nele — mesmo com valores altos.
Checklist de diagnóstico antes de tocar no número:
- O elemento está posicionado?
z-indexexigepositiondiferente destatic. - Algum ancestral cria stacking context? Suspeitos comuns:
transform,filter,opacity < 1,isolation: isolate. - O overlay está dentro de um container com
overflow: hiddenque recorta o conteúdo? - O problema é de layout ou de ordem no DOM, não de
z-index?
Fluxo operacional para diagnóstico rápido:
- No DevTools, selecione o elemento que deveria estar no topo.
- Suba na árvore de pais procurando propriedades que criam contexto.
- Se houver contexto indevido, remova-o ou mova o overlay para fora do container.
- Só depois disso, ajuste a escala de camadas.
Para alinhar linguagem entre dev e QA, padronize os sintomas mais comuns:
- "Tooltip atrás do modal" indica tooltip renderizado dentro de um contexto inferior.
- "Dropdown atrás do header sticky" costuma ser ausência de faixa reservada para flutuantes.
A documentação da MDN sobre z-index é a referência oficial para manter na wiki do time.
Z-Index como token de design: faixas que não colidem
Se você quer previsibilidade, trate z-index como token, não como ajuste local. A régua de camadas funciona quando você reserva faixas para famílias de componentes — isso elimina a escalada do 999999 e reduz conflitos entre squads.
O AWS Cloudscape Design System é um bom exemplo de método: intervalos definidos para headers sticky, dropdowns e modais. A lição não é copiar os números, é copiar a abordagem — componentes previsíveis exigem faixas previsíveis.
Modelo recomendado de escala (adapte à sua realidade):
| Camada | Faixa | Exemplos |
|---|---|---|
| Base do conteúdo | 0–99 | Cards, imagens, texto |
| Elementos fixos | 100–199 | Header sticky, nav fixa |
| Flutuantes | 200–299 | Dropdown, autocomplete |
| Tooltips e popovers | 300–399 | Tooltips, hints |
| Modais e drawers | 500–599 | Modais, sidebars |
| Bloqueios globais | 700+ | Toasts críticos, loaders globais |
Use passos de 10 ou 100 para permitir inserções futuras sem refatorar tudo.
Como operacionalizar em time:
- Crie um documento "Mapa de Camadas" com nomes e intenção de cada faixa.
- Bloqueie valores fora da escala em PR via lint ou revisão obrigatória.
- Sempre que surgir um novo tipo de camada, adicione ao mapa e versione.
Implementação em código: CSS Variables, Tailwind e tokens centralizados
Uma escala só vira realidade quando é fácil de aplicar. A combinação mais robusta para a maioria dos times: tokens centralizados, nomes semânticos e um ponto único de edição.
Implementação base com CSS Variables:
:root {
--z-base: 0;
--z-header: 100;
--z-dropdown: 200;
--z-tooltip: 300;
--z-modal: 500;
--z-global: 700;
}
.header { position: sticky; z-index: var(--z-header); }
.modal { position: fixed; z-index: var(--z-modal); }
Regra de decisão para PR:
- Se o
z-indexnão usavar(--z-...), o PR não passa. - Se alguém precisa de um novo token, ele entra no mapa e no
:root.
Para quem usa Tailwind, dá para tematizar a escala e evitar números mágicos no markup. O suporte a z-index via @theme no Tailwind v4 — discutido no repositório oficial — permite criar utilitários coerentes como z-tooltip e z-modal sem inventar valores por componente.
Para equipes com muita variação de produtos, um gerador é ainda mais escalável: uma lista ordenada de camadas em JavaScript vira variáveis CSS automaticamente, e a ordenação vira a fonte da verdade. O artigo "A Better Way to Manage Z-Indexes" mostra uma abordagem leve para isso.
Ponto de controle de implementação:
- Tokens em um único arquivo.
- Camadas nomeadas, não numeradas no markup.
- Revisão de código focada em intenção, não em matemática.
Ferramentas para depurar z-index: DevTools, extensões e inventário de camadas
Mesmo com padrões, bugs acontecem. O diferencial é ter ferramentas que reduzam o tempo de diagnóstico de horas para minutos.
Workflow operacional recomendado (15 minutos para chegar na causa raiz):
- Abra o DevTools e selecione o elemento que está "sumindo".
- Confirme
positione o token aplicado. - Liste elementos concorrentes: header, modal, overlay de terceiros.
- Procure stacking contexts ancestrais que prendem o componente.
- Ajuste arquitetura (portal, DOM, container) antes de aumentar a camada.
Para acelerar o passo 3, a extensão DevTools z-index adiciona uma visão ordenada por valores de z-index no Chrome. Ela é especialmente útil para identificar guerras do tipo 99999 espalhadas pela base de código.
Para times grandes, crie um inventário de camadas em ambiente de componentes:
- Publique os principais overlays no Storybook e valide combinações relevantes.
- Mantenha stories que renderizam "header + dropdown + modal + tooltip" juntos.
- Registre a escala no próprio design system, ao lado de espaçamento e cores.
Métricas que vale acompanhar:
- Tempo médio de resolução de bugs de camada por sprint.
- Quantidade de valores fora da escala encontrados em revisão de código.
Menos exceções significa menos retrabalho — e esse número conecta diretamente qualidade de código com custo operacional.
Overlays em apps modernas: React Portals, bibliotecas e contextos presos
Em aplicações modernas, o problema não é só CSS. Bibliotecas de UI e ferramentas de debug também inserem overlays. Quando esses overlays são renderizados dentro de um container que cria stacking context, o z-index pode ficar inútil independentemente do valor.
Regra prática de arquitetura: overlays globais (modal, drawer, tooltip, devtools) devem ser renderizados próximos do <body>.
No ecossistema React, isso significa usar portals. Um exemplo real desse problema aparece na discussão de z-index do React Query Devtools, com proposta de renderização via portal no repositório do TanStack Query. A ideia é evitar que o overlay fique preso em contextos criados pelo layout do app.
Checklist de decisão para adoção de portal:
- O componente precisa aparecer acima de qualquer coisa do app? Use portal.
- O componente depende de
overflow: hiddenlocal (ex.: dropdown dentro de um card)? Resolva com posicionamento local. - Existe
transformno layout raiz (ex.: animações de página)? Portal vira praticamente obrigatório para modais confiáveis.
Cuidados com integração:
- Em iframes, o topo do
z-indexdo iframe não ultrapassa o topo do documento pai. - Overlays de terceiros podem ter escalas próprias — mapeie isso no seu inventário.
Quando surgir um conflito recorrente, registre como dívida técnica e trate como padrão de plataforma, não como hotfix.
QA e validação: como testar camadas sem depender de "olhômetro"
A maioria dos times só percebe problemas de z-index quando alguém clica e "não dá para ver". Para evitar isso, QA precisa de critérios objetivos e uma rotina de validação — não de inspeção manual a cada deploy.
Critérios de aceite prontos para usar em tickets:
- Dropdown sempre aparece acima do header e abaixo do modal.
- Tooltip nunca fica atrás do backdrop.
- Modal bloqueia interação com o conteúdo, inclusive elementos sticky.
- Nenhum componente usa
z-indexfora da escala definida.
Cobertura mínima de cenários compostos:
- Modal aberto + tooltip em elemento dentro do modal.
- Header sticky + autocomplete aberto.
- Drawer aberto + toast global.
Automação prática em pipeline:
- Playwright para capturar estados de overlay com screenshots e regressão visual.
- Cypress para fluxos e asserts de visibilidade em stacks que já o utilizam.
- Chromatic para diffs visuais em PRs com Storybook.
Regra de decisão de QA para falha de camada:
- Componente invisível: investigar stacking context e portal antes de qualquer outra coisa.
- Componente visível mas atrás do alvo errado: comparar tokens e ajustar a régua.
- Comportamento intermitente: suspeitar de animações e
transformem containers pai.
Próximos passos
z-index deixa de ser "mágica negra" quando vira contrato documentado. Com faixas claras, tokens semânticos e um inventário de overlays, a pilha visual passa a ser previsível — e ferramentas como DevTools, Storybook e testes visuais transformam caça ao bug em diagnóstico rápido.
Passo imediato: crie um "Mapa de Camadas" com 8 a 12 tokens, aplique via variáveis CSS ou tema do seu framework, e bloqueie exceções em PR. Na semana seguinte, adicione três cenários compostos no Storybook e um teste visual automatizado. Essa sequência costuma eliminar a maior parte dos conflitos de z-index em poucas sprints.