¿Por qué un elemento con un valor de índice z no puede cubrir a su hijo?

Resuelto ZYinMD asked hace 5 años • 4 respuestas

Hoy, después de horas de depuración, aprendí por las malas que:

Un elemento principal nunca puede cubrir (apilarse encima) de su elemento secundario si el elemento principal tiene un índice z de cualquier valor, sin importar cómo cambie el CSS del niño.

¿Cómo puedo entender este comportamiento por lógica? ¿Está en las especificaciones?

.container {
  width: 600px;
  height: 600px;
  background-color: salmon;
  position: relative;
  z-index: 99;
  padding-top: 10px;
}

h1 {
  background-color: pink;
  position: relative;
  z-index: -1;
  font-family: monospace;
}
<div class="container">
  <h1>1. I can never be covered by parent if my z-index is positive.</h1>
  <h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>
Expandir fragmento

Hijo de índice z negativo sobre el elemento padre

ZYinMD avatar Feb 27 '19 11:02 ZYinMD
Aceptado

Hay dos cosas importantes que debes saber: el orden de pintura y el contexto de apilamiento. Si consulta las especificaciones , podrá saber cómo y cuándo se pintan los elementos.

  1. Contextos de apilamiento formados por descendientes posicionados con índices z negativos (excluyendo 0) en orden de índice z (el más negativo primero) y luego en orden de árbol.

  1. Todos los descendientes posicionados, de opacidad o transformados, en orden de árbol, que se clasifican en las siguientes categorías:

    1. Todos los descendientes posicionados con 'z-index: auto' o 'z-index: 0', en orden de árbol.

  1. Contextos de apilamiento formados por descendientes posicionados con índices z mayores o iguales a 1 en el orden del índice z (el más pequeño primero) y luego en el orden del árbol.

De esto se desprende claramente que primero pintamos los elementos con negativo z-indexen el paso (3), luego los que tienen z-indexigual a 0 en el paso (8) y finalmente los que tienen positivo z-indexen el paso (9), lo cual es lógico. También podemos leer en otra parte de la especificación :

Cada cuadro pertenece a un contexto de apilamiento . Cada cuadro en un contexto de apilamiento determinado tiene un nivel de pila entero, que es su posición en el eje z en relación con otros cuadros en el mismo contexto de apilamiento . Las cajas con niveles de pila más altos siempre se formatean delante de las cajas con niveles de pila más bajos. Las cajas pueden tener niveles de pila negativos. Las cajas con el mismo nivel de pila en un contexto de apilamiento se apilan de abajo hacia arriba según el orden del árbol de documentos.


Para comprender cuándo se pintará cada elemento, necesita conocer su contexto de apilamiento y su nivel de pila dentro de este contexto de apilamiento (definido por z-index). También necesitas saber si ese elemento establece un contexto de apilamiento. Esta es la parte complicada, porque la configuración z-indexhará esto:

Para un cuadro posicionado, la propiedad del índice z especifica:

  1. El nivel de pila de la caja en el contexto de apilamiento actual.
  2. Si la caja establece un contexto de apilamiento

Los valores tienen los siguientes significados:

<integer>

Este número entero es el nivel de pila del cuadro generado en el contexto de apilamiento actual. La caja también establece un nuevo contexto de apilamiento .

auto

El nivel de pila del cuadro generado en el contexto de apilamiento actual es 0. El cuadro no establece un nuevo contexto de apilamiento a menos que sea el elemento raíz.


Ahora tenemos toda la información para entender mejor cada caso. Si el elemento principal tiene un z-indexvalor distinto de auto, creará un contexto de apilamiento, por lo que el elemento secundario se pintará dentro de lo que sea z-index(negativo o positivo). El z-indexdel elemento hijo simplemente nos dirá el orden de pintura dentro del elemento padre (esto cubre el segundo punto) .

Ahora, si solo el elemento hijo tiene un positivo z-indexy no configuramos nada en el elemento padre, considerando el orden de pintura, el hijo se pintará más tarde (en el paso (9)) y el padre en el paso (8). La única forma lógica de pintar el padre de arriba es aumentar el z-index, pero hacer esto nos hará caer en el caso anterior donde el padre establecerá un contexto de apilamiento y el elemento hijo pertenecerá a él.

No hay forma de tener el elemento principal encima de un elemento secundario al establecer un elemento positivo z-index para el elemento secundario. Además, no hay forma de tener el padre encima del hijo si configuramos un z-indexelemento padre diferente de auto(ya sea positivo o negativo). 1

El único caso en el que podemos tener un hijo debajo de su padre es establecer un valor negativo z-indexen el elemento hijo y mantener el padre en z-index: auto, por lo que este no creará un contexto de apilamiento y, siguiendo el orden de pintura, el hijo se pintará primero.


Además z-index, existen otras propiedades que crean un contexto de apilamiento . En caso de que se enfrente a un orden de apilamiento esperado, también debe considerar esas propiedades para ver si se ha creado un contexto de apilamiento.


Algunos hechos importantes que podemos concluir de lo anterior:

  1. Los contextos de apilamiento pueden estar contenidos en otros contextos de apilamiento y juntos crean una jerarquía de contextos de apilamiento.
  2. Cada contexto de apilamiento es completamente independiente de sus hermanos : solo se consideran los elementos descendientes cuando se procesa el apilamiento.
  3. Cada contexto de apilamiento es autónomo : después de apilar el contenido del elemento, todo el elemento se considera en el orden de apilamiento del contexto de apilamiento principal. árbitro

1 : hay algunas formas complicadas si consideramos el uso de la transformación 3D.

Ejemplo con un elemento que va debajo de su elemento padre incluso si éste tiene un z-indexespecificado.

Mostrar fragmento de código

Otro ejemplo donde podemos colocar un elemento entre dos elementos en otro contexto de apilamiento:

Mostrar fragmento de código

También podemos tener un orden de apilamiento loco como el siguiente:

Mostrar fragmento de código

Contexto de apilamiento circular CSS

Debemos tener en cuenta que el uso de dicho truco puede tener algún efecto secundario debido al hecho de que transform-styleafectará perspectiveal elemento. Relacionado: ¿Por qué la aplicación de un filtro CSS en el elemento principal altera la posición del elemento secundario?transformposition:absolute/fixed

Temani Afif avatar Feb 27 '2019 10:02 Temani Afif

Una buena forma de pensar en esto es que cada padre contiene su propio contexto de apilamiento. Los elementos hermanos comparten el orden de apilamiento de los padres y, por lo tanto, pueden superponerse entre sí.

Un elemento secundario SIEMPRE obtiene un contexto de apilamiento basado en su elemento principal. De ahí la necesidad de un valor de índice z negativo para empujar al niño "detrás" de su contexto de apilamiento principal (0).

La única forma de eliminar un elemento del contexto de su padre es usarlo, position: fixedya que esto esencialmente lo obliga a usar la ventana para el contexto.

Bryce Howitson avatar Feb 27 '2019 04:02 Bryce Howitson

La documentación de Mozilla dice

La propiedad CSS z-index establece el orden z de un elemento posicionado y sus descendientes o elementos flexibles.

Aquí hay alguna lógica adicional de otro artículo de StackOverflow relacionado con hijos versus descendientes.

Dani Amsalem avatar Feb 27 '2019 04:02 Dani Amsalem