Provavelmente quase todos nós, pelo menos uma vez na vida, usamos a propriedade z-index. Além disso, cada desenvolvedor tem certeza de que sabe como funciona. De fato, o que poderia ser mais simples do que operações com números inteiros (comparando e atribuindo-os a elementos). Mas tudo é tão simples quanto parece à primeira vista?
Talvez a informação que abordarei abaixo seja realmente trivial. No entanto, tenho certeza de que muitos acharão útil para si mesmos. Aqueles que já sabiam disso poderão usar este texto como uma cábula em tempos difíceis. Bem-vindo ao gato.
De fato, uma pessoa geralmente começa a tentar descobrir um novo campo para si mesma em três casos: se encontra resultados inesperados no trabalho e não entende o que está acontecendo; se houver necessidade de ir além e olhar o assunto de um ângulo diferente; e, finalmente, apenas por interesse esportivo.
Meu caso claramente não pertence à terceira categoria. No começo, várias vezes na minha vida me deparei com o primeiro cenário ao trabalhar em diferentes projetos; no entanto, ele não entendeu completamente o problema devido à preguiça e à falta de materiais claros e compreensíveis com exemplos. E então, no início deste ano, comecei a escrever um mecanismo da Web, o que me fez começar a ler padrões e geralmente ver
como várias coisas não triviais funcionam em navegadores populares e, mais importante,
por que elas funcionam dessa maneira.
Vamos começar com um simples. O que é o índice z e para que serve?
Obviamente, essa é a coordenada ao longo do eixo Z, especificada para algum elemento. O eixo Z é direcionado para o usuário. Um número maior é um elemento mais próximo.

Por que os números do índice z são inteiros? Tudo é simples. O intervalo é praticamente ilimitado na parte superior e inferior, portanto, não precisamos usar valores fracionários. Como o monitor real não possui uma terceira dimensão (só podemos simulá-lo), precisamos de uma quantidade sem dimensão, cuja única tarefa é fornecer uma comparação dos elementos (isto é, a ordem do conjunto). Inteiros fazem um excelente trabalho nessa tarefa, enquanto são mais visuais que reais.
Parece que esse conhecimento é suficiente para começar a usar o z-index nas páginas. No entanto, nem tudo é tão simples.
<div style="background: #b3ecf9; z-index: 1"></div> <div style="background: #b3ecb3; margin-top: -86px; margin-left: 38px; z-index: 0"></div>

Algo parece ter dado errado. Fizemos o primeiro bloco z-index mais que o segundo, então por que ele é exibido abaixo? Sim, ele passa pelo código anteriormente - mas parece que isso deve desempenhar um papel apenas com valores iguais de índice z.
Neste ponto, é hora de abrir o padrão CSS2.1, ou melhor, o aplicativo, referente ao processamento de contextos de sobreposição. Aqui está o
link .
A partir deste texto pequeno e muito conciso, você pode extrair imediatamente muitas informações importantes.
- Sobreposição de controle do índice z não sobre elementos individuais, mas contextos de sobreposição (grupos de elementos)
- Não podemos controlar arbitrariamente elementos em contextos diferentes entre si: aqui a hierarquia funciona. Se já estamos em um contexto "baixo", não podemos torná-lo um elemento acima do elemento de um contexto "superior".
- O z-index não faz sentido para elementos em um fluxo normal (para o qual a propriedade position é estática). Caímos nessa armadilha no exemplo acima.
- Para que um elemento defina um novo contexto de sobreposição, ele deve ser posicionado e deve ser atribuído um índice z.
- Se o elemento estiver posicionado, mas o índice z não estiver definido, podemos assumir condicionalmente que ele é igual a zero (em casos simples, isso funciona assim, consideraremos as nuances posteriormente).
- E os contextos de sobreposição individuais são definidos por elementos com um valor de opacidade menor que um. Isso foi feito para que você possa transferir facilmente a mistura alfa para o último estágio de renderização para processamento pela placa de vídeo.
Mas isso não é tudo. Acontece que, com elementos sem z-index, também não é tão simples quanto parece.
O processo de renderização de elementos da subárvore de contexto pode ser dividido em vários estágios (os dois primeiros estão produzindo diretamente a cor e a imagem de plano de fundo do elemento atual que define o contexto).
Então, considere a lista inteira.
3. Derivação de contextos filhos com índice z negativo
4. Saída de elementos do bloco filho em um fluxo normal (apenas planos de fundo)
5. Saída de elementos flutuadores filhos
6. A saída do conteúdo dos elementos em um fluxo normal: descendentes em linha e em bloco inline, conteúdo em linha dentro de descendentes em bloco, incluindo linhas de texto *
7. A saída de contextos filhos com zero e z-index automático **
8. Derivação de contextos filhos com índice z positivo
* para atravessar a primeira árvore em profundidade
** para contextos com z-index: auto, considere todos os contextos filhos como descendentes do contexto atual, ou seja, "puxe" para o nível atual
Já não é tão fácil, certo? Você pode ilustrar esse esquema com a seguinte figura:

Também é possível abrir um exemplo no
codepen e brincar com ele com suas próprias mãos.
Mas isso não é tudo. Parece que o algoritmo já é bastante complicado: primeiro precisamos puxar os contextos filhos dentro dos pseudo-contextos (lembre-se do valor auto?). Em seguida, classifique duas listas de índices z, organizando-as em uma série numérica, e depois analise as crianças: primeiro, bloqueie em um fluxo normal, flutuando, inline e inline-block ...
Mas aqui estamos aguardando duas surpresas. O primeiro, com sorte, não vai nos interessar. Isso está relacionado ao fato de que o plano de fundo com quadros e o conteúdo dos elementos do bloco são exibidos em diferentes estágios - mas se o nosso mecanismo criado por cada nó de texto criar um elemento embutido automaticamente, tudo ficará bem, eles serão exibidos posteriormente naturalmente.
Mas o segundo não é tão trivial. Está marcado
Para cada uma delas, trate o elemento como se tivesse criado um novo contexto de empilhamento, mas todos os descendentes posicionados e descendentes que realmente criarem um novo contexto de empilhamento devem ser considerados parte do contexto de empilhamento pai, não este novo.
elementos float e inline-block / inline (mas não block!).
O que isso significa na prática? E isso significa que devemos processá-los da mesma maneira que os elementos com z-index: auto. Ou seja, em primeiro lugar, percorra as subárvores e retire os contextos filhos de lá, colocando-os no nível atual. Mas, quanto ao resto, devemos tratá-los como elementos que definem nosso contexto.
Isso significa que todas as subárvores dentro delas, estendidas após um rastreamento para uma lista linear, devem permanecer atômicas. Ou, em outras palavras, não podemos embaralhar a ordem dos elementos para que os descendentes desse elemento “flutuem” acima de seus pais. E se para contextos filhos é intuitivamente claro (porque o algoritmo é recursivo), então aqui não é assim.
Portanto, ao escrever o código do mecanismo, temos que nos enganar para que os elementos float, inline e inline-block por enquanto não revelem seus descendentes (com exceção de crianças com posicionamento e índice z, que formam contextos de sobreposição) e, em seguida, execute-os a função inteira é recursiva, mas, pelo contrário, levando em consideração o fato de que os contextos filhos devem ser ignorados durante uma travessia.
Alguns exemplos para demonstrar esse fenômeno:
<div style="float: left; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: -1; top: -20px; left: -20px;"></div> </div>

Aqui a criança tem z-index e está posicionada. Ele aparece, mas é exibido sob um quadrado azul, pois os elementos com índice z negativo são exibidos no estágio 3 e os elementos flutuantes no estágio 5.
<div style="float: left; margin-top: -30px; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> <div style="background: #b3ecb3; margin-top: 52px; margin-left: 38px;"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div>

Neste exemplo, o segundo elemento (verde) é exibido antes do primeiro (azul) e, portanto, abaixo. No entanto, as crianças são atraídas (porque definem seus próprios contextos); portanto, nesse caso, elas seguem na mesma ordem em que vão exatamente na árvore original (a ordem de seus ancestrais após a permutação não é importante!). Se definirmos o primeiro filho como z-index igual a 1, obteremos a seguinte imagem:

Adicione mais elementos.
<div style="float: left; background: #b3ecf9;"> <div style="float: left"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> </div> <div style=" background: #b3ecb3; margin-top: 32px; margin-left: 40px;"> <div style="position: relative"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div> </div>

Aqui, os contextos filhos são extraídos dos carros alegóricos e dos blocos comuns, enquanto a ordem é preservada como estava na árvore original.
Finalmente, o último exemplo:
<div style="background: #b3ecf9;"> <div style="display: inline-block; width: 40px; height: 40px; background: #fc0;"></div> </div> <div style="background: #b3ecb3; margin-top: -100px; margin-left: 22px;"></div>

Como você pode ver, "saltar" de um elemento de bloco é, em contraste com outros casos, bastante possível, e como temos um elemento de bloco embutido aparecendo, será o último deste documento.
Como você pode ver, o índice z permite executar muitos truques interessantes (que vale pelo menos ocultar o elemento sob seu pai imediato usando um índice z negativo no filho). Espero que este artigo tenha sido útil para você.