Propriedade z-index: Controlando a ordem de empilhamento

Aprenda a definir qual elemento aparece por cima de outro.

Quando você começa a usar position (relative, absolute, fixed, sticky), é muito comum que elementos se sobreponham uns aos outros. Nesses casos, surge a pergunta: qual elemento deve aparecer por cima e qual deve ficar por baixo? É aí que entra a propriedade z-index.

A propriedade z-index controla a ordem de empilhamento de elementos posicionados. Pense nela como uma "profundidade" ou "camada" em um eixo Z (que vai para dentro e para fora da tela). Elementos com um z-index maior aparecem por cima de elementos com um z-index menor.

Imagine que a tela do seu computador é um palco. Os elementos são atores. Se dois atores tentam ocupar o mesmo espaço, z-index decide quem fica na frente (mais perto da plateia) e quem fica atrás.

Como funciona z-index

  1. Apenas para Elementos Posicionados: A propriedade z-index só tem efeito em elementos que possuem um position diferente de static (ou seja, relative, absolute, fixed ou sticky). Elementos static não podem ter seu z-index alterado.

  2. Valores:

    • auto (padrão): O elemento herda a ordem de empilhamento do seu pai.
    • Número inteiro: Aceita qualquer número inteiro (positivo, negativo ou zero). Números maiores significam que o elemento está "mais à frente" e aparecerá por cima.
      • Exemplo: z-index: 1;, z-index: 100;, z-index: -1;
  3. Contexto de Empilhamento (Stacking Context): Este é um conceito crucial. O z-index de um elemento só é relevante dentro do seu próprio contexto de empilhamento.

    • Um novo contexto de empilhamento é criado por elementos com position diferente de static (e z-index diferente de auto), ou por outras propriedades CSS como opacity menor que 1, transform, filter, will-change, entre outras.

    • Regra de Ouro: O z-index de um elemento filho só pode ser comparado com o z-index de seus irmãos dentro do mesmo contexto de empilhamento. O z-index de um elemento pai não é diretamente comparado com o z-index de um elemento que está fora de sua hierarquia.

    • Exemplo: Se você tem um div-pai com z-index: 1; e dentro dele um div-filho com z-index: 100;, e fora do div-pai você tem um div-irmao com z-index: 2;, o div-irmao (com z-index: 2) ainda aparecerá por cima do div-filho (com z-index: 100), porque o div-filho está "preso" ao contexto de empilhamento do div-pai (que tem z-index: 1).

Ordem de Empilhamento Padrão (sem z-index)

Quando não há z-index definido, a ordem de empilhamento segue algumas regras:

  1. Elementos de Bloco: Aparecem na ordem em que estão no HTML.
  2. Elementos Inline: Aparecem na ordem em que estão no HTML.
  3. Elementos Posicionados: Aparecem por cima dos elementos não posicionados, na ordem em que estão no HTML.

Exemplo Prático:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Propriedade Z-index</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      background-color: #f4f4f4;
    }

    .box {
      width: 150px;
      height: 150px;
      text-align: center;
      line-height: 150px;
      font-weight: bold;
      color: white;
      font-size: 1.2em;
      position: absolute; /* Essencial para z-index funcionar */
    }

    .box1 {
      background-color: red;
      left: 50px;
      top: 50px;
      z-index: 1; /* Por cima do box2 */
    }

    .box2 {
      background-color: blue;
      left: 100px;
      top: 100px;
      z-index: 2; /* Por cima do box1 e box3 */
    }

    .box3 {
      background-color: green;
      left: 150px;
      top: 150px;
      z-index: 0; /* Por baixo do box1 e box2 */
    }

    .container-context {
      width: 300px;
      height: 300px;
      background-color: #ccc;
      border: 2px solid black;
      margin-top: 250px; /* Para não sobrepor os boxes acima */
      position: relative; /* Cria um contexto de empilhamento */
      z-index: 10; /* Z-index do container */
    }

    .child-box-a {
      background-color: purple;
      left: 20px;
      top: 20px;
      z-index: 100; /* Alto z-index, mas dentro do contexto do pai */
    }

    .sibling-box-b {
      background-color: orange;
      left: 200px;
      top: 200px;
      z-index: 5; /* Z-index menor que o container-context */
      position: absolute; /* Para que o z-index funcione */
    }
  </style>
</head>
<body>
  <h1>Exemplo Básico de `z-index`</h1>

  <div class="box box1">Box 1 (z-index: 1)</div>
  <div class="box box2">Box 2 (z-index: 2)</div>
  <div class="box box3">Box 3 (z-index: 0)</div>

  <p style="margin-top: 250px;">Observe a ordem de empilhamento: Box 2 (azul) está por cima de Box 1 (vermelho), que está por cima de Box 3 (verde).</p>

  <h1>Exemplo de Contexto de Empilhamento</h1>

  <div class="container-context">
    Container (z-index: 10)
    <div class="box child-box-a">Child A (z-index: 100)</div>
  </div>

  <div class="box sibling-box-b">Sibling B (z-index: 5)</div>

  <p style="margin-top: 50px;">
    Mesmo com Child A tendo `z-index: 100`, ele está dentro do Container (z-index: 10).
    Sibling B (z-index: 5) está fora do Container.
    O Sibling B (z-index: 5) aparecerá por cima do Child A (z-index: 100), porque o contexto de empilhamento do Container (z-index: 10) é menor que o z-index do Sibling B.
    A ordem de empilhamento é determinada pelos contextos de empilhamento, e não apenas pelos valores absolutos de `z-index`.
  </p>
</body>
</html>

Resultado:

  • No primeiro exemplo, você verá que o Box 2 (azul, z-index: 2) está por cima do Box 1 (vermelho, z-index: 1), que por sua vez está por cima do Box 3 (verde, z-index: 0).
  • No segundo exemplo, você notará que o "Sibling B" (laranja, z-index: 5) aparece por cima do "Child A" (roxo, z-index: 100), mesmo tendo um z-index menor. Isso acontece porque o "Child A" está dentro do "Container" (que tem z-index: 10), e o "Sibling B" está fora