Cómo funciona realmente el índice z

Probablemente casi todos nosotros, al menos una vez en nuestra vida, usamos la propiedad del índice z. Además, cada desarrollador está seguro de que sabe cómo funciona. De hecho, lo que podría ser más simple que las operaciones con enteros (comparándolos y asignándolos a elementos). ¿Pero es todo tan simple como parece a primera vista?

Quizás la información que cubriré a continuación es realmente trivial. Sin embargo, estoy seguro de que muchos lo encontrarán útil para sí mismos. Aquellos que ya lo sabían podrán usar este texto como una hoja de trucos en tiempos difíciles. Así que bienvenido al gato.

imagen

De hecho, una persona generalmente comienza a tratar de resolver un nuevo campo para sí misma en tres casos: si encuentra resultados inesperados en el trabajo y no comprende lo que está sucediendo; si es necesario ir más allá y mirar el sujeto desde un ángulo diferente; y finalmente, solo por interés deportivo.

Mi caso claramente no pertenece a la tercera categoría. Al principio, varias veces en mi vida me encontré con el primer escenario cuando trabajaba en diferentes proyectos; sin embargo, no entendió completamente el problema debido a la pereza y la falta de materiales claros y comprensibles con ejemplos. Y luego, a principios de este año, comencé a escribir un motor web, lo que me hizo comenzar a leer estándares y, en general, a ver cómo funcionan las diferentes cosas no triviales en los navegadores populares, y lo más importante, por qué funcionan de esa manera.

Comencemos con uno simple. ¿Qué es el índice z y para qué sirve?

Obviamente, esta es la coordenada a lo largo del eje Z, especificada para algún elemento. El eje Z se dirige hacia el usuario. Un número mayor es un elemento más cercano.

imagen

¿Por qué los números del índice z son enteros? Todo es simple El rango es prácticamente ilimitado en la parte superior e inferior, por lo que no necesitamos usar valores fraccionarios. Dado que el monitor real no tiene una tercera dimensión (solo podemos simularlo), necesitamos una cantidad adimensional, cuya única tarea es proporcionar una comparación de los elementos (es decir, el orden del conjunto). Los enteros hacen un excelente trabajo de esta tarea, mientras que son más visuales que los reales.

Parece que este conocimiento es suficiente para comenzar a usar el índice z en las páginas. Sin embargo, no todo es tan simple.

<div style="background: #b3ecf9; z-index: 1"></div> <div style="background: #b3ecb3; margin-top: -86px; margin-left: 38px; z-index: 0"></div> 

imagen

Algo parece haber salido mal. Hicimos el primer índice z del bloque más que el segundo, entonces, ¿por qué se muestra a continuación? Sí, pasa por el código anteriormente, pero parece que esto debería jugar un papel solo con valores de índice z iguales.

En este punto, es hora de abrir el estándar CSS2.1, o más bien la aplicación, con respecto al procesamiento de contextos superpuestos. Aquí está el enlace .

De este texto pequeño y muy conciso, puede extraer de inmediato mucha información importante.

  1. Superposición de control de índice z no sobre elementos individuales, sino contextos de superposición (grupos de elementos)
  2. No podemos controlar arbitrariamente elementos en diferentes contextos entre sí: aquí funciona la jerarquía. Si ya estamos en un contexto "bajo", entonces no podemos convertirlo en un elemento por encima del elemento de un contexto "superior".
  3. El índice z no tiene ningún sentido para los elementos en una secuencia normal (para los cuales la propiedad de posición es estática). Caímos en esta trampa en el ejemplo anterior.
  4. Para que un elemento defina un nuevo contexto de superposición, debe colocarse y debe asignarse un índice z.
  5. Si el elemento está posicionado, pero el índice z no está establecido, entonces podemos suponer condicionalmente que es igual a cero (para casos simples, esto funciona así, consideraremos los matices más adelante).
  6. Y los contextos de superposición individuales están establecidos por elementos con un valor de opacidad menor que uno. Esto se hizo para que pueda transferir fácilmente la mezcla alfa a la última etapa de procesamiento para que la tarjeta de video la procese.

Pero eso no es todo. Resulta que con elementos sin índice z tampoco es tan simple como parece.

El proceso de representación de elementos del subárbol de contexto se puede dividir en varias etapas (las dos primeras generan directamente el color de fondo y la imagen de fondo del elemento actual que establece el contexto).

Entonces, considere la lista completa.

3. Derivación de contextos secundarios con índice z negativo
4. Salida de elementos de bloque hijo en un flujo normal (solo fondos)
5. Salida de elementos flotantes secundarios
6. La salida del contenido de elementos en una secuencia normal: descendientes en línea y en bloque en línea, contenido en línea dentro de descendientes en bloque, incluidas líneas de texto *
7. La salida de contextos secundarios con cero e índice z automático **
8. Derivación de contextos secundarios con índice z positivo

* para atravesar el árbol de profundidad primero
** para contextos con índice z: automático, considere todos los contextos secundarios como descendientes del contexto actual, es decir, "llévelos" al nivel actual

Ya no es tan fácil, ¿verdad? Puede ilustrar este esquema con la siguiente imagen:

imagen

También es posible abrir un ejemplo en codepen y jugar con tus propias manos.

Pero eso no es todo. Parece que el algoritmo ya es bastante complicado: primero debemos extraer los contextos secundarios dentro de los pseudocontextos (¿recuerdan el valor auto?), Luego ordenar dos listas de índice z, organizarlas en una serie de números, luego pasar por los elementos secundarios: primero por bloque en una secuencia normal, luego flotante, luego en línea y en bloque en línea ...

Pero aquí estamos esperando dos sorpresas. El primero, con suerte, no nos concierne. Está relacionado con el hecho de que el fondo con marcos y el contenido de los elementos de bloque se muestran en diferentes etapas, pero si nuestro motor creado por cada nodo de texto crea un elemento en línea automáticamente, entonces todo estará bien, naturalmente se mostrarán más tarde.

Pero el segundo no es tan trivial. Esta marcado
Para cada uno de estos, trate el elemento como si creara un nuevo contexto de apilamiento, pero cualquier descendiente posicionado y descendiente que realmente cree un nuevo contexto de apilamiento debe considerarse parte del contexto de apilamiento primario, no este nuevo.

elementos flotantes e inline-block / inline (pero no block!).

¿Qué significa esto en la práctica? Y esto significa que debemos procesarlos de la misma manera que los elementos con z-index: auto. Es decir, en primer lugar, recorrer sus subárboles y extraer contextos secundarios desde allí, colocándolos en el nivel actual. Pero por lo demás, debemos tratarlos como elementos que definen nuestro contexto. Esto significa que todos los subárboles dentro de ellos, estirados después de un rastreo en una lista lineal, deben permanecer atómicos. O, en otras palabras, no podemos barajar el orden de los elementos para que los descendientes de dicho elemento "floten" por encima de sus padres. Y si para contextos secundarios es intuitivamente claro (porque el algoritmo es recursivo), entonces aquí no es así.

Por lo tanto, al escribir el código del motor, tenemos que engañarnos para que los elementos flotante, en línea y en bloque en línea por el momento no revelen sus descendientes (con la excepción de los niños con posicionamiento e índice z, que forman contextos de superposición), y luego corremos por ellos toda la función es recursiva, pero por el contrario, teniendo en cuenta el hecho de que los contextos secundarios deben omitirse durante un recorrido.

Algunos ejemplos para demostrar este 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> 

imagen

Aquí el niño tiene índice z y está posicionado. Aparece, pero se muestra debajo de un cuadrado azul, ya que los elementos con índice z negativo se muestran en la etapa 3 y los elementos flotantes en la etapa 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> 

imagen

En este ejemplo, el segundo elemento (verde) se muestra antes del primero (azul) y, por lo tanto, a continuación. Sin embargo, los niños son detenidos (porque establecen sus propios contextos), por lo que en este caso van en el mismo orden en que van exactamente en el árbol original (¡el orden de sus antepasados ​​después de la permutación no es importante!). Si establecemos el primer hijo en el índice z igual a 1, entonces obtenemos la siguiente imagen:

imagen

Agrega más 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> 

imagen

Aquí, los contextos secundarios se extraen tanto de flotantes como de bloques ordinarios, mientras que el orden se conserva como estaba en el árbol original.

Finalmente, el último ejemplo:

 <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> 

imagen

Como puede ver, "saltar" de un elemento de bloque es, en contraste con otros casos, bastante posible, y dado que aparece un elemento de bloque en línea, será el último en este documento.

Como puede ver, el índice z le permite realizar muchos trucos interesantes (que vale la pena al menos ocultar el elemento debajo de su elemento primario inmediato utilizando un índice z negativo en el elemento secundario). Espero que este artículo te haya sido útil.

Source: https://habr.com/ru/post/es431046/


All Articles