Contextos de empilhamento e Z-index

Podcast sobre o CSS - 019: Z-index e pilhas de contexto (em inglês)

Digamos que você tenha alguns elementos que estão absolutamente posicionados e que devem ser posicionados uns sobre os outros. Você pode escrever um pouco de um HTML como este:

<div class="stacked-items">
    <div class="item-1">Item 1</div>
    <div class="item-2">Item 2</div>
</div>

Mas qual fica em cima da outra, por padrão? Para saber qual item faz isso, você precisa entender o Z-index e os contextos de empilhamento.

Z-index

A propriedade z-index define explicitamente uma ordem de camadas para HTML com base no espaço 3D do navegador, o eixo Z. Esse é o eixo que mostra quais camadas estão mais perto e mais longe de você. O eixo vertical na Web é o eixo Y e o eixo horizontal é o X.

Cada eixo ao redor do elemento

A propriedade z-index aceita um valor numérico que pode ser um número positivo ou negativo. Os elementos aparecerão acima de outro se tiverem um valor z-index mais alto. Se nenhum z-index for definido nos elementos, o comportamento padrão é que a ordem de origem do documento determine o eixo Z. Isso significa que os elementos mais abaixo no documento ficam sobre os elementos que aparecem antes deles.

No fluxo normal, se você definir um valor específico para z-index e ele não estiver funcionando, será necessário definir o valor position do elemento como algo diferente de static. Esse é um lugar comum em que as pessoas têm dificuldade com o z-index.

No entanto, isso não vai acontecer se você estiver em um contexto de grade ou flexbox, porque é possível modificar o Z-index de itens flexíveis ou da grade sem adicionar position: relative.

Z-index negativo

Para definir um elemento atrás de outro, adicione um valor negativo para z-index.

.my-element {
    background: rgb(232 240 254 / 0.4);
}

.my-element .child {
    position: relative;
    z-index: -1;
}

Contanto que .my-element tenha o valor inicial de auto para z-index, o elemento .child ficará atrás dele.

Adicione o seguinte CSS ao .my-element, e o elemento .child não ficará atrás dele.

.my-element {
  position: relative;
  z-index: 0;
  background: rgb(232 240 254 / 0.4);
}

Como .my-element agora tem um valor de position que não é static e um valor de z-index que não é auto, um novo contexto de empilhamento foi criado. Isso significa que, mesmo que você defina .child para ter um z-index de -999, ele ainda não fica atrás de .my-parent.

Contexto de acumulação

Um contexto de empilhamento é um grupo de elementos que têm um pai comum e que se movem para cima e para baixo no eixo z juntos.

Nesse exemplo, o primeiro elemento pai tem um z-index de 1, então, cria um novo contexto de empilhamento. O elemento filho tem um z-index de 999. Ao lado desse pai, há outro elemento pai com um filho. O elemento pai tem um z-index de 2, e o elemento filho também tem um z-index de 2. Como os dois pais criam um contexto de empilhamento, o z-index de todos os filhos é baseado no do pai.

O z-index dos elementos dentro de um contexto de empilhamento é sempre relativo à ordem atual do pai no próprio contexto de pilha.

Como criar um contexto de empilhamento

Não é necessário aplicar z-index e position para criar um novo contexto de empilhamento. É possível criar um novo contexto de empilhamento adicionando um valor para as propriedades que criam uma nova camada composta, como opacity, will-change e transform. Veja uma lista completa de propriedades aqui.

Para explicar o que é uma camada composta, imagine que uma página da Web é uma tela. O navegador usa seu HTML e CSS para determinar o tamanho do canvas. Em seguida, ele pinta a página nessa tela. Se um elemento mudar (por exemplo, de posição), o navegador terá que voltar e redefinir o que pintar.

Para ajudar no desempenho, o navegador cria novas camadas compostas que são colocadas em cima da tela. Esses são um pouco como post-its: mover um e alterá-lo não tem um grande impacto no canvas geral. Uma nova camada composta é criada para elementos com opacity, transform e will-change porque eles têm grandes chances de mudar. Por isso, o navegador usa a GPU para aplicar ajustes de estilo e garantir o melhor desempenho possível para essa mudança.

Recursos

Teste seu conhecimento

Teste seus conhecimentos sobre z-index

<section>
  <article>1</article>
  <article>2</article>
  <article>3</article>
  <article>4</article>
</section>

Qual artigo é exibido na parte superior por padrão?

1
Está bem no fundo.
2
Tente de novo.
3
Tente de novo.
4
O último no documento está no topo, sim!

Se o Z-index não estiver funcionando, qual propriedade você precisa inspecionar no elemento?

display
Essa não é a propriedade provável que explica por que o Z-index não está funcionando.
relative
Esse é um valor de CSS, não uma propriedade.
position
Verifique se essa opção está definida como algo diferente de static.
animation
Essa não é a propriedade provável que explica por que o Z-index não está funcionando.

O flexbox e a grade precisam de position: relative?

Sim
Esses tipos de tela não precisam dessa informação.
Não
O uso do Z-index em um layout flexbox ou de grade funcionará sem position: relative.