Artigo original: CSS Z-Index Not Working? How to Fix It Using Stack Order

A propriedade z-index do CSS pode ser bastante complicada. Ela não funciona facilmente e por conta própria se você não souber como usá-la adequadamente.

Neste artigo, explicarei o que é a propriedade z-index, o que é a ordem de empilhamento e como usá-las da maneira certa.

Darei alguns exemplos comuns do funcionamento inadequado da propriedade z-index e mostrarei as soluções para eles.

O que é o z-index?

Em primeiro lugar, a letra Z vem da representação das três dimensões: x, y e z. x e y são a largura e a altura. A 3ª dimensão, z, é a profundidade:

xyz

O CSS fornece uma propriedade chamada z-index para que possamos usá-la para determinar a profundidade de um elemento. À medida que o valor de z-index de um elemento aumenta, mais à frente dos outros elementos ele estará posicionado com relação à 3ª dimensão.

Vejamos alguns exemplos e como usar a propriedade z-index corretamente.

A propriedade z-index não funciona sem uma posição definida nem com position: static

A primeira coisa importante a se saber é que todo elemento de uma página da web tem uma posição padrão – em outras palavras, uma posição definida estaticamente (por padrão). Digamos que temos uma caixa vermelha e outra azul em nossa página:

<div class="caixa caixa-vermelha"></div>
<div class="caixa caixa-azul"></div>
1

Se aplicarmos z-index às caixas diretamente, você verá que isso não dará resultado. Isso ocorre por não termos ainda uma posição (a propriedade position) definida:

.caixa {
  height: 150px;
  width: 150px;
}

.caixa-vermelha {
  background: red;
  z-index: 1;
}

.caixa-azul {
  background: #00d5f1;
  bottom: 80px;
  left: 55px;
  z-index: 2;
}

Esse é um dos exemplos mais comuns da propriedade z-index, onde ela não funciona corretamente. Para resolvê-lo, podemos aplicar uma propriedade position (texto em inglês) à classe caixa. Isto resolverá a questão:

.caixa {
  height: 150px;
  width: 150px;
  position: relative;
}
2

Você também pode assistir a este tutorial em vídeo para ver um exemplo de uso de z-index:

O que é a ordem de empilhamento?

Se removermos as propriedades z-index das duas caixas, a caixa azul seguira à frente da caixa vermelha, mesmo sem um valor para a propriedade z-index:

.caixa {
  height: 150px;
  width: 150px;
  position: relative;
}

.caixa-vermelha {
  background: red;
}

.caixa-azul {
  background: #00d5f1;
  bottom: 80px;
  left: 55px;
}

A renderização será a seguinte:

image-153

Desse modo, quando todos os elementos estão no mesmo nível, um elemento ainda ficará à frente do outro, pois eles também têm uma ordem padrão em termos do eixo z. Essa ordem é chamada de ordem de empilhamento.

Como no exemplo acima, quando não há uma propriedade z-index aplicada a um elemento, os navegadores usam uma ordem de empilhamento padrão para empilhar os elementos na página:

1. O segundo plano e as bordas do elemento root
2. Blocos descendentes não posicionados, em ordem de aparecimento no HTML
3. Blocos descendentes posicionados, em ordem de aparecimento no HTML

Fonte: Stacking without the z-index property (texto em inglês)

Observe que o elemento root é o elemento <html>. Os elementos não posicionados são aqueles que têm a propriedade position com seu valor padrão, position: static, e os elementos posicionados são aqueles que têm elementos com position definida como outro valor.

Se adicionarmos outra caixa, mas se definirmos sua propriedade position com o valor padrão static, ela aparecerá atrás das caixas vermelha e azul:

<div class="caixa caixa-vermelha"><p>Positioned</p></div>
<div class="caixa caixa-azul"><p>Positioned</p></div>
<div class="caixa caixa-amarela"><p>Non-positioned</p></div>
.caixa {
  height: 150px;
  width: 150px;
  position: absolute;
}

p {
  color: #0a0a23;
  margin: 0;
  padding-left: 5px;
}

.caixa-vermelha {
  background: red;
  top: 40px;
  left: 27px;
}

.caixa-azul {
  background: #00d5f1;
  top: 80px;
  left: 55px;
}

.caixa-amarela {
  background: rgb(251, 239, 0);
  position: static;
}

Este é o resultado:

image-156
Caixa amarela não posicionada (non-positioned, em inglês) e caixas vermelha e azul posicionadas (positioned, em inglês)

Embora tenhamos modificado as caixas azul e vermelha para que usassem position: absolute em vez de relative e tenhamos ajustado um pouco seu posicionamento, a ideia era auxiliar a perceber a ordem padrão de empilhamento no navegador – elementos posicionados no mesmo nível sempre aparecerão sobre os elementos não posicionados (ou com a propriedade definida como position: static).

Você pode estar se perguntando o que acontece quando os elementos não estiverem no mesmo nível. Veremos isso agora.

Contexto de empilhamento: Como o z-index do elemento pai se aplica também ao elemento filho

Vamos colocar a caixa amarela entre a caixa vermelha e a azul:

<div class="caixa caixa-vermelha">
  <div class="caixa caixa-amarela"></div>
</div>
<div class="caixa caixa-azul"></div>
.caixa-vermelha {
  background: red;
  z-index: 1;
}

.caixa-azul {
  background: #00d5f1;
  bottom: 80px;
  left: 55px;
  z-index: 2;
}

.caixa-amarela {
  background: rgb(251, 239, 0);
  left: 25px;
  top: 25px;
  z-index: 3;
}

Teremos renderizado o seguinte:

3

Como é possível ver no código, mesmo que a caixa amarela tenha um valor dez-index maior em comparação ao elemento azul, ela está posicionada atrás da caixa azul.

Isso ocorre porque a caixa amarela agora é "filha" da caixa vermelha. O z-index do elemento "pai" sempre se aplica aos seus filhos também. Como o elemento pai tem um z-index menor que o da caixa azul, seus elementos filhos herdarão o mesmo valor de z-index e ficarão abaixo da caixa com o valor de z-index maior no mesmo nível que o elemento pai.

Isso ocorre por causa de algo chamado contexto de empilhamento. Colocado de maneira simples, um contexto de empilhamento é como uma nova instância da lista da ordem de empilhamento mencionada anteriormente, ou seja:

  1. Um elemento root (<html>)
  2. Elementos não posicionados (com position: static) na ordem em que aparecem
  3. Elementos posicionados (com position definida com outro valor que não static) na ordem em que aparecem

O que devemos lembrar é que o elemento posicionado com um valor de z-index diferente do padrão auto (que o deixará com posicionamento estático) criará sempre um outro contexto de empilhamento.

Se olharmos para o HTML acima, como a caixa vermelha tem um z-index de 1, ela cria outro contexto de empilhamento para seus filhos – no caso, para a caixa amarela. Nesse contexto de empilhamento, a caixa vermelha funciona como se fosse o elemento root do HTML. A caixa amarela estaria posicionada dentro desse elemento root.

Assim, como a caixa azul é parte do mesmo contexto de empilhamento que a caixa vermelha (onde o elemento <html> é o que serve como elemento root), ela sempre aparecerá acima da caixa amarela.

Caso veja esse tipo de problema, você pode resolvê-lo removendo o elemento filho de dentro do elemento pai ou removendo a propriedade position do elemento pai, de modo que o z-index do pai não afete seus filhos:

<div class="caixa caixa-vermelha"></div>
<div class="caixa caixa-amarela"></div>
<div class="caixa caixa-azul"></div>
.caixa {
  height: 150px;
  width: 150px;
  position: relative;
}

.caixa-vermelha {
  background: red;
  z-index: 1;
}

.caixa-azul {
  background: #00d5f1;
  bottom: 240px;
  left: 55px;
  z-index: 2;
}

.caixa-amarela {
  background: rgb(251, 239, 0);
  bottom: 120px;
  left: 25px;
  z-index: 3;
}

Agora, o que temos é:

image-158

Saiba que existem diversas outras propriedades que podem afetar o contexto de empilhamento de um elemento. Leia mais sobre isso aqui (texto em inglês).

Isso é um pouco contraintuitivo, mas é uma das razões para o não funcionamento da propriedade z-index.

Não atribua números grandes ao z-index

Outro motivo comum para o z-index não funcionar corretamente é a atribuição de números muito altos à propriedade z-index:

.caixa-azul {
  z-index: 9999;
}

Em alguns projetos nos quais já trabalhei, vi pessoas atribuírem esses valores muito grandes, como 9999, ao z-index de um elemento.

Funciona, mas é como usar um martelo quando o que você precisa é de uma chave de fenda.

Imagine o seguinte – você chega em um projeto grande e trabalha com o HTML, mas, não importa o que você tente, não consegue colocar os elementos na ordem correta. Assim, após pesquisar um pouco on-line, você descobre que alguém, em algum momento, definiu uma propriedade z-index global como 9999, que segue sobrescrevendo seu z-index.

Agora que você sabe como usar a propriedade z-index adequadamente e que entende o contexto de empilhamento, não precisará mais usar valores enormes como aquele. 🙂

Espero que este artigo tenha ajudado você a entender melhor como usar a propriedade z-index, assim como a ordem de empilhamento e o contexto do empilhamento. Se quiser aprender mais sobre desenvolvimento para a web, não deixe de se inscrever no canal do YouTube do autor.

Agradecemos pela leitura!