O que ninguém te contou sobre a propriedade z-index

O problema com z-index é que muito pouca gente compreende como funciona realmente. Não é complicado, mas se você nunca se deu ao trabalho de ler sua especificação, há certamente alguns aspectos cruciais que você passou por alto.

Você não acredita? Bem, vejamos se você pode resolver este problema:

O problema

No HTML a seguir você tem três elementos <div>, e cada <div> contém um único elemento <span>. Cada <span> tem uma cor de fundo — vermelho, verde e azul respectivamente. Cada <span> está também posicionado absolutamente próxima da posição superior esquerda do documento, mal encobrindo os outros elementos <span> assim que você pode ver quais estão empilhados em frente de cada um. O primeiro <span> tem um valor z-index de 1, enquanto que os outros dois não tem nenhum valor z-index fixado.

Aqui temos o HTML e CSS básicos para entendê-lo. Também incluí uma demo  visual (via Codepen) com o código que se mostra a continuação:

<div>
<span>Vermelho</span>
</div>
<div>
<span>Verde</span>
</div>
<div>
<span>Azul</span>
</div>
.vermelho, .verde, .azul {
position: absolute;
}
.vermelho {
background: red;
z-index: 1;
}
.verde {
background: green;
}
.azul {
background: blue;
}

Aqui está o desafio: tente ver se pode fazer com que o <span> vermelho se empilhe detrás do azul e do verde sem romper nenhuma das seguintes regras:

  • Não altere o HTML de nenhuma maneira.
  • Não acrescente ou mude a propriedade z-index de nenhum elemento.
  • Não acrescente ou mude a propriedade de posicionamento de nenhum elemento.
  • Para que você possa ter uma ideia clara, clique em”edit” no link de Codepen que há acima e jogue um momento com o código.
Advertência: Não clique na aba de CSS ou te dará imediatamente a resposta.

 

A solução

A solução é acrescentar um valor de opacidade menor que 1no primeiro <div> (o pai do <span> vermelho). Aqui está o CSS que se acrescenta ao Codepen:

div:first-child {
opacity: .99;
}

Se você está coçando a cabeça neste momento em estado de shock e parece espantado pelo fato dessa opacidade ter causado efeito no modo como os elementos se empilham uns em relação aos outros, bem-vindo ao clube. A mim me passou o mesmo quando me deparei pela primeira vez com o mesmo problema.

Fique tranquilo, o resto do artigo deixará as coisas um pouco mais claras.

Ordenar o empilhamento

Z-index parece simples: elementos com um z-index maior são empilhados diante dos elementos com um menor z-index, não? Bem, na verdade, não. Isto é parte do problema do z-index. Parece simples e por isso os desenvolvedores não dedicam tempo para ler suas regras.

Cada elemento em um documento HTML pode estar diante ou detrás de outro elemento no documento. Isto se conhece como a ordem de empilhamento. As regras que determinam esta ordem estão bonitas e claramente definidas na especificação, porém como constatei, não são completamente entendidas pela maioria dos desenvolvedores.

Quando o z-index e as propriedades de posição não estão declaradas, as regras são muito simples: basicamente, a ordem de empilhamento é o mesmo que a ordem de aparição no HTML. (DE ACORDO, é na verdade um pouco mais complicado que isso, mas se você não estiver usando margens negativas para dissimular elementos na mesma linha de posição, provavelmente não encontrará elementos problemáticos).

Quando você introduz a propriedade de posição na mistura, quaisquer elementos posicionados (e seus filhos) se mostram diante de elementos não posicionados (dizemos que um elemento está “posicionado” quando tem um valor de posição distinto de “static”, como “relative”, “absolute”, etc.)

Finalmente, quando o z-index se envolve também, as coisas se complicam um pouco. No começo é natural assumir que os elementos com valores z-index maiores estão diante dos elementos com valores z-index menores, e que qualquer elemento com z-index está em frente aos elementos que não têm z-index, mas não é tão simples. Primeiro de tudo, z-index só funciona com elementos posicionados. Se você tenta atribuir um z-index a um elemento sem posição especificada, não fará nada. Em segundo lugar, os valores z-index podem criar contextos de empilhamento e agora de repente o que parecia simples é bastante mais complicado.

Contextos de empilhamento

Grupos de elementos com um pai comum que se movem para frente ou para trás juntos na ordem de empilhamento, se integram no que é conhecido como contexto de empilhamento. Uma completa compreensão dos contextos de empilhamento é a chave para realmente captar como funciona o z-index e a ordem de empilhamento.

Cada contexto de empilhamento tem um elemento HTML como seu elemento raiz. Quando um novo contexto de empilhamento se forma em um elemento, esse contexto confina todos os seus elementos filhos em um lugar particular da ordem. Isso significa que se um elemento estiver contido em um contexto de empilhamento no mais baixo da ordem, não há maneira de que apareça diante de outro elemento em um contexto de empilhamento que esteja em um nível superior na ordem, inclusive com um z-index de mil milhões!

Os novos contextos de empilhamento podem ser formados em um elemento de três maneiras:

  • Quando um elemento é o elemento raiz de um documento (o elemento <html>).
  • Quando um elemento tem um valor de posição que não seja “static” e valor de z-index distinto de “auto”.
  • Quando um elemento tem um valor de opacidade menor que um.

A primeira e a segunda maneira de formar contextos de empilhamento têm muito sentido e são geralmente bem compreendidos pelos desenvolvedores web (inclusive se não conhecem o próprio conceito de contexto de empilhamento).

A terceira maneira (opacidade) é apenas mencionada fora dos documentos de especificação da W3C.

Determinando uma posição de elemento na ordem de empilhamento

Atualmente, determinar a ordem de empilhamento global para todos os elementos de uma página (incluindo bordas, fundos, camadas de texto, etc.) é extremamente complicado e foge do propósito deste artigo (de novo, faço referencia à especificação). Porém, para nosso propósito, uma compreensão básica da ordem pode ajudar a desenvolver um CSS previsível. Desse modo, vamos dividir a ordem em contextos individuais de empilhamento:

Ordem de empilhamento dentro do mesmo contexto de empilhamento

Aqui estão as regras básicas de ordem de empilhamento dentro de um contexto simples (do fundo hem diante):

  1. O contexto de empilhamento do elemento raiz.
  2. Elementos posicionados (e seus filhos) com valores z-index negativos (os valores mais altos são empilhados diante de valores menores; elementos com o mesmo valor são empilhados de acordo com sua aparição no HTML).
  3. Elementos não posicionados (ordenados por aparição no HTML).
  4. Elementos posicionados (e sus filhos) com um valor z-index de auto (ordenados por aparição no HTML).
  5. Elementos posicionados (e seus filhos) com valores z-index positivos (os valores maiores são empilhados diante de valores menores; elementos com o mesmo valor são empilhados de acordo com sua aparição no HTML.
Nota: elementos posicionados com z-indexes negativos se ordenam primeiro dentro de um contexto de empilhamento, o que significa que aparecem detrás de outros elementos. Por causa disto, chega a ser possível para um elemento aparecer detrás de seu próprio pai, o que normalmente não é possível. Isto funcionará somente se o elemento parental estiver no mesmo contexto de empilhamento e não for o elemento raiz desse contexto de empilhamento. Um grande exemplo disto são os drop-shadows com CSS e sem imagens de Nicolas Gallagher.

 

Ordem de empilhamento global

Com uma firme compreensão de como funcionam os contextos de empilhamento e de como funciona a ordem de empilhamento dentro de um contexto de empilhamento, imaginar onde um elemento particular poderá aparecer na ordem de empilhamento global se converte em uma tarefa mais simples.

O segredo é evitar a confusão gerada quando se formam novos contextos de empilhamento. Se você colocar um z-index com um valor de mil milhões em um elemento e não se mover para a frente na ordem de empilhamento, dê uma olhada no seu ascendente e veja se algum de seus pais está formando contextos de empilhamento. Se estiverem, seu z-index é inútil e não faz nada bem.

Conclusão

Voltemos ao problema original, onde recriei a estrutura HTML acrescentando comentários dentro de cada etiqueta indicado seu lugar na ordem de empilhamento.

<div><!– 1 –>
<span><!– 6 –></span>
</div>
<div><!– 2 –>
<span><!– 4 –><span>
</div>
<div><!– 3 –>
<span><!– 5 –></span>
</div>

Quando acrescentamos a regra de opacidade o primeiro <div>, a ordem de empilhamento muda assim:

<div><!– 1 –>
<span><!– 1.1 –></span>
</div>
<div><!– 2 –>
<span><!– 4 –><span>
</div>
<div><!– 3 –>
<span><!– 5 –></span>
</div>

“span.vermelho” costumava ser 6, mas mudou para 1.1. Se mostra que um novo contexto de empilhamento foi criado, e “span.vermelho” é agora o primeiro elemento dentro desse novo contexto.

Espero que agora esteja um pouco mais claro por que a caixa vermelha se moveu detrás das outras caixas. O exemplo original continha só dois contextos de empilhamento, a raiz e o formado por “span.vermelho” Quando acrescentamos opacidade ao elemento pai de “span.vermelho”, formamos um terceiro contexto de empilhamento e, como resultado, o valor z-index de “span.vermelho” só se aplicava dentro desse novo contexto. Como o primeiro <div> (o único a que aplicamos opacidade) e seus elementos irmãos não têm atribuídos nem posição nem valor de z-index, sua ordem de empilhamento é determinado por sua ordem de aparição no HTML, o que significa que o primeiro <div>, e todos os elementos contidos dentro de seu contexto de empilhamento são renderizados detrás do segundo e do terceiro <div>.

Fonte: http://www.criarweb.com/artigos/propiedade-z-index.html

Deixe um comentário