Dlaczego element o wartości z-index nie może pokryć swojego potomka?

Dzisiaj po godzinach debugowania, nauczyłem się tej zasady na własnej skórze:

Element nadrzędny nigdy nie jest w stanie pokryć (stos na wierzchu) swojego elementu podrzędnego, jeśli rodzic ma indeks z dowolnej wartości, bez względu na to, jak zmienisz CSS potomka

Jak mogę zrozumieć to zachowanie logicznie? Jest w specyfikacji?

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

Ujemny z-Indeks potomka nad elementem rodzica

Author: Temani Afif, 2019-02-27

4 answers

Są dwie ważne rzeczy, które musisz wiedzieć: porządek malowania i kontekst układania. Jeśli odwołujesz się do specyfikacji , możesz dowiedzieć się, jak i kiedy elementy są malowane.

  1. układanie kontekstów utworzonych przez potomków z ujemnymi indeksami z (wyłączając 0) w kolejności z-indeksów (najpierw najbardziej ujemne), a następnie w kolejności drzewa.

  1. wszystkie pozycje, nieprzezroczystość lub transformacja Potomków, w kolejności drzew, które należą do następujących kategorii:
    1. wszystkie umieszczone potomkinie Z 'Z-index: auto' lub 'z-index: 0', w kolejności drzewa.

  1. stosowanie kontekstów utworzonych przez umieszczonych potomków z indeksami z większymi lub równymi 1 W porządku z-indeksów (najpierw najmniejszym), a następnie porządku drzewa.

Z tego wynika, że najpierw malujemy elementy z ujemnym z-index w kroku (3), następnie ten z z-index równym 0 Na kroku (8), i wreszcie te z dodatnim z-index na kroku (9), co jest logiczne. Możemy również przeczytać w innej części specyfikacji :

Każde pudełko należy do jednego kontekstu układania . Każde pole w danym kontekście stosu ma poziom stosu liczb całkowitych, który jest jego położeniem na osi z względem innych pól w tym samym kontekście stosu. Pola z większymi poziomami stosu są zawsze formatowane z przodu skrzynek o niższych poziomach stosu. Skrzynki mogą mieć ujemny poziom stosu. Pola o tym samym poziomie stosu w kontekście stosu są układane od dołu do góry zgodnie z kolejnością drzewa dokumentów.

Również

Element, który ustanawia lokalny kontekst stosu, generuje pole, które ma dwa poziomy stosu: jeden dla tworzonego kontekstu stosu (zawsze 0) i jeden dla kontekstu stosu, do którego należy (podany przez właściwość z-index).


To aby zrozumieć, kiedy każdy element będzie malowany, musisz znać jego kontekst stosu i jego poziom stosu wewnątrz tego kontekstu stosu (zdefiniowanego przez z-index). Musisz również wiedzieć, czy ten element ustanawia kontekst układania. Jest to najtrudniejsza część, ponieważ ustawienie z-index zrobi to:

Dla pola pozycjonowanego właściwość z-index określa:

  1. poziom stosu pola w bieżącym kontekście układania.
  2. czy box ustanawia kontekst stosu

Wartości mają następujące znaczenia:

<integer>

Ta liczba całkowita jest poziomem stosu wygenerowanego pola w bieżącym kontekście układania. Ramka również ustanawia nowy kontekst układania .

auto

Poziom stosu wygenerowanego pola w bieżącym kontekście stosu wynosi 0. Pole nie ustanawia nowego kontekstu stosu, chyba że jest to root element.


Teraz mamy wszystkie informacje, aby lepiej zrozumieć każdy przypadek. Jeśli element nadrzędny ma wartość z-index czegoś innego niż auto, to utworzy kontekst układania, a więc element potomny będzie malowany wewnątrz niezależnie od tego, czy jest to z-index (ujemny czy dodatni). z-index elementu potomnego po prostu powie nam kolejność malowania wewnątrz elementu nadrzędnego (dotyczy to drugiego punktu) .

Teraz, jeśli tylko element potomny ma dodatni z-index i nie ustawiamy nic na elemencie nadrzędnym, wtedy biorąc pod uwagę kolejność malowania, dziecko będzie malowane później (w kroku (9)), A rodzic w kroku (8). Jedynym logicznym sposobem malowania rodzica powyżej jest zwiększenie z-index, ale to spowoduje, że wpadniemy w poprzedni przypadek, w którym rodzic ustanowi kontekst układania i element potomny będzie do niego należał.

Nie ma nie ma możliwości aby mieć rodzica nad elementem potomnym podczas ustawiania pozytywny z-index za dziecko. Nie ma również sposobu, aby mieć rodzica nad potomkiem, jeśli ustawimy z-index na element rodzica inny niż auto (dodatni lub ujemny).1

Jedynym przypadkiem, w którym możemy mieć dziecko poniżej jego rodzica, jest ustawienie ujemnego z-index na elemencie potomnym i utrzymanie rodzica na z-index: auto, więc ten nie utworzy kontekstu układania i zgodnie z kolejnością malowania dziecko będzie malowane najpierw.


Oprócz z-index, istnieją inne właściwości, które tworzą kontekst stosu . Jeśli napotkasz oczekiwaną kolejność układania, musisz również wziąć pod uwagę te właściwości, aby sprawdzić, czy istnieje kontekst układania.


Kilka ważnych faktów, które możemy wywnioskować z powyższego:

  1. konteksty układania mogą być zawarte w innych kontekstach układania i razem tworzyć hierarchię kontekstów układania.
  2. każdy kontekst stosu jest całkowicie niezależny od jego rodzeństwa : tylko elementy potomne są brane pod uwagę podczas przetwarzania stosu.
  3. każdy kontekst stosu jest samowystarczalny : po ułożeniu zawartości elementu cały element jest rozpatrywany w kolejności stosu nadrzędnego kontekstu stosu. ref

1: jest kilka hakerskich sposobów, jeśli weźmiemy pod uwagę użycie 3D transformacja.

Przykład z elementem wchodzącym pod jego element nadrzędny, nawet jeśli ten ma z-index podany.

.box {
  position:relative;
  z-index:0;
  height:80px;
  background:blue;
  transform-style: preserve-3d; /* This is important */
}
.box > div {
  margin:0 50px;
  height:100px;
  background:red; 
  z-index:-1; /* this will do nothing */
  transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
  <div></div>
</div>

Kolejny przykład, w którym możemy umieścić element między dwoma elementami w innym kontekście stosu:

.box {
  position: relative;
  z-index: 0;
  height: 80px;
  background: blue;
}

.box>div {
  margin: 0 50px;
  height: 100px;
  background: red;
  z-index: 5;
  transform: translateZ(2px);
}

.outside {
  height: 50px;
  background: green;
  margin: -10px 40px;
  transform: translateZ(1px);
}

body {
  transform-style: preserve-3d;
}
<div class="box">
  <div></div>
</div>

<div class="outside"></div>

Możemy również mieć jakieś szalone kolejność układania jak poniżej:

.box {
  width: 100px;
  height: 100px;
  position: absolute;
}

body {
  transform-style: preserve-3d;
}
<div class="box" style="top:100px;left:50px;background:red;"></div>
<div class="box" style="top: 50px;left: 115px;background:blue;"></div>
<div class="box" style="top: 101px;left: 170px;background:green;"></div>
<div class="box" style="top: 175px;left: 115px;background:purple;transform: rotateY(-1deg);"></div>

CSS circular stacking context

Należy zauważyć, że za pomocą takie hack może mieć jakieś skutki uboczne ze względu na fakt, że transform-style, perspective i transform wpłynie na position:absolute/fixed element. Powiązane: CSS-filtr na rodzica przerywa pozycjonowanie dziecka

 40
Author: Temani Afif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-18 10:18:34

Dobrym sposobem myślenia o tym jest to, że każdy rodzic zawiera swój własny kontekst układania. Elementy rodzeństwa mają wspólny porządek układania rodzica i w związku z tym mogą się nakładać na siebie.

Element potomny zawsze otrzymuje kontekst układania oparty na jego rodzicu. Stąd potrzeba ujemnej wartości indeksu z, aby popchnąć dziecko " za " jego rodzica (0) kontekstu układania.

Jedynym sposobem na usunięcie elementu z kontekstu rodzica jest użycie position: fixed, ponieważ zasadniczo zmusza go to do użycia okno kontekstu.

 3
Author: Bryce Howitson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-27 04:32:59

Dokumentacja Mozilli mówi

Właściwość CSS z-index ustawia kolejność z pozycjonowanego elementu i jego potomków lub elementów flex.

Oto dodatkowa logika z innego artykułu Stoskoverflow dotyczącego dzieci vs Potomków.

 2
Author: Dani Amsalem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-27 04:23:42

Jak mogę zrozumieć to zachowanie logicznie?

Dla mnie trudno zrozumieć twój problem logicznie. Rodzic zawiera swoje dzieci. Miska może być przykryta inną miską. Ale nie możesz przykryć zupy miską, chyba że wyjmiesz zupę z miski.

Z-Index ustawia kolejność nakładających się elementów. Rodzic nie może nakładać się na swoje dziecko.

ImhO to całkiem logiczne.
 1
Author: Olafant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-27 06:02:12