¿Por qué un elemento con un valor de índice z no puede cubrir a su hijo?
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>
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.
- 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.
Todos los descendientes posicionados, de opacidad o transformados, en orden de árbol, que se clasifican en las siguientes categorías:
- Todos los descendientes posicionados con 'z-index: auto' o 'z-index: 0', en orden de árbol.
- 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-index
en el paso (3), luego los que tienen z-index
igual a 0 en el paso (8) y finalmente los que tienen positivo z-index
en 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-index
hará esto:
Para un cuadro posicionado, la propiedad del índice z especifica:
- El nivel de pila de la caja en el contexto de apilamiento actual.
- 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-index
valor 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-index
del 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-index
y 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-index
elemento 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-index
en 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:
- Los contextos de apilamiento pueden estar contenidos en otros contextos de apilamiento y juntos crean una jerarquía de contextos de apilamiento.
- Cada contexto de apilamiento es completamente independiente de sus hermanos : solo se consideran los elementos descendientes cuando se procesa el apilamiento.
- 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-index
especificado.
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
Debemos tener en cuenta que el uso de dicho truco puede tener algún efecto secundario debido al hecho de que transform-style
afectará perspective
al elemento. Relacionado: ¿Por qué la aplicación de un filtro CSS en el elemento principal altera la posición del elemento secundario?transform
position:absolute/fixed
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: fixed
ya que esto esencialmente lo obliga a usar la ventana para el contexto.
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.