Przewodnik po CSS z-index i kontekstach nakładania
CSS z-index nie działa? Konteksty nakładania, widok 3D | We.Inc
Dlaczego z-index jest ignorowany, każda właściwość tworząca kontekst nakładania, rozłożony widok warstw w 3D, sticky nagłówki i dropdowny, skala z-index oraz checklista debugowania.
z-index ustala kolejność nakładających się elementów, ale tylko w obrębie tego samego kontekstu nakładania (stacking context). Dziecko z z-index: 9999 nie wzniesie się ponad element spoza swojego rodzica, jeśli ten rodzic tworzy kontekst z niższym z-index. Konteksty powstają z position w połączeniu z z-index, opacity poniżej 1, transform, filter, isolation: isolate i kilku innych właściwości.
Dlaczego z-index wydaje się ignorowany
Objaw
Prawdopodobna przyczyna
z-index nic nie zmienia
Element ma position: static i nie jest dzieckiem flex ani grid
Ogromny z-index, a element nadal pod spodem
Przodek tworzy kontekst nakładania na niższej warstwie
Dropdown schowany pod następną sekcją
Rodzic ma transform, opacity lub filter
Menu przycięte na krawędzi
overflow: hidden na przodku, z-index nie ma tu nic do rzeczy
Widok 3D poniżej rozkłada małą stronę na warstwy nakładania, abyś zobaczył, które elementy są uwięzione w którym kontekście. Zmieniaj wartości z-index i przełączaj na rodzicu właściwość tworzącą kontekst. Dalej: wszystkie wyzwalacze według MDN, sticky nagłówki z dropdownami, skala tokenów i krok po kroku procedura debugowania.
Ustaw wartości z-index dla nagłówka, karty i dropdownu wewnątrz karty.
Przełącz na karcie wyzwalacz kontekstu nakładania i zobacz, jak dropdown zostaje uwięziony.
Włącz widok 3D, aby zobaczyć warstwy rozdzielone i pogrupowane według kontekstu.
Użyj isolation: isolate lub przenieś dropdown poza kontekst, aby to naprawić.
Zanim podniesiesz liczbę, znajdź kontekst nakładania. Podnoszenie z-index wewnątrz uwięzionego kontekstu nigdy nie pomaga.
Trzymaj wartości z-index w nazwanych tokenach z odstępami między nimi, aby nowe warstwy mieściły się bez przenumerowywania.
Używaj isolation: isolate na komponentach, aby zamknąć w nich wewnętrzne wartości z-index i nie dopuścić do konfliktów z resztą strony.
Dla modali i popoverów natywny element dialog i atrybut popover korzystają z top layer, która znajduje się ponad każdym z-index.
Najczęściej zadawane pytania
Dlaczego z-index nie działa?
Albo element nie jest pozycjonowany (z-index wymaga position innego niż static albo rodzica flex lub grid), albo jest uwięziony w kontekście nakładania. O wyniku decyduje pozycja rodzica w jego własnym kontekście, a dzieci nie mogą się z niego wydostać, niezależnie od liczby, jaką mają.
Co tworzy kontekst nakładania?
Element główny, pozycjonowane elementy z z-index, elementy fixed i sticky, dzieci flex i grid z z-index, opacity poniżej 1, transformacje, filtry, clip-path, maski, mix-blend-mode, perspective, isolation: isolate, niektóre wartości contain i will-change, kontenery rozmiaru oraz elementy top layer.
Co robi isolation: isolate?
Tworzy nowy kontekst nakładania i nic poza tym, bez żadnej zmiany wizualnej. Umieść ją na elemencie głównym komponentu, aby dzieci z ujemnym z-index zostały za własnym tłem komponentu, zamiast spaść za stronę, i aby jego wewnętrzne warstwy nigdy nie mieszały się z zewnętrznymi.
Jak utrzymać dropdown nad następną sekcją?
Nadaj nagłówkowi lub kontenerowi z dropdownem wyższy z-index niż sekcjom po nim, przy czym oba muszą być pozycjonowane. Jeśli kontener ma transform lub opacity, pamiętaj, że to osobny kontekst, więc z-index musi trafić na ten kontener, a nie na dropdown.
Czy ujemny z-index jest bezpieczny?
Jest poprawny, ale element trafia za tło swojego kontekstu nakładania. Bez kontekstu na rodzicu może to oznaczać schowanie za tłem strony i niewidoczność. Dodaj isolation: isolate na rodzicu, aby został w środku.
Jak działa kolejność malowania
W obrębie jednego kontekstu nakładania przeglądarka maluje w stałej kolejności: najpierw tło samego kontekstu, potem dzieci z ujemnym z-index, następnie zwykłą treść blokową, elementy float, treść inline, pozycjonowane elementy z z-index auto lub 0 w kolejności w źródle, a na końcu dodatni z-index od najniższego do najwyższego.
Kontekst potomny jest malowany jako jedna całość w miejscu rodzica na tej liście. Wszystko w środku jest sortowane wyłącznie względem rodzeństwa. To jedyny powód, dla którego 9999 wewnątrz karty z z-index: 1 przegrywa z sąsiadem z z-index: 2.
Procedura debugowania
Najpierw upewnij się, że to problem z nakładaniem: jeśli element jest ucięty prostą krawędzią, szukaj raczej overflow na przodku. Potem w DevTools idź w górę od ukrytego elementu i sprawdzaj w computed styles każdego przodka wyzwalacze wymienione na tej stronie.
DevTools w Chromium ma panel Layers, a Edge ma 3D View, które pokazują wizualnie złożone warstwy. Gdy znajdziesz przodka tworzącego kontekst, podnieś go, usuń wyzwalacz albo wyrenderuj pływający element poza nim.
Wszystko, co tworzy kontekst nakładania
Na podstawie dokumentacji MDN o stacking context. Wystarczy spełnienie dowolnego jednego warunku.
Wyzwalacze kontekstu nakładania
Właściwość lub stan
Warunek
Element główny
html jest zawsze głównym kontekstem nakładania
position: absolute lub relative
Tylko z z-index innym niż auto
position: fixed lub sticky
Zawsze, z-index nie jest potrzebny
Dziecko flex lub grid
Z z-index innym niż auto, nawet jeśli position jest static
container-type: size lub inline-size
Każdy element będący kontenerem zapytań o rozmiar
opacity poniżej 1
Także opacity: 0.99
Dowolna wartość inna niż normal
transform, scale, rotate, translate
Dowolna wartość inna niż none
filter lub backdrop-filter
Dowolna wartość inna niż none
Dowolna wartość inna niż none
Dowolna wartość inna niż none
mask, mask-image, mask-border
Dowolna wartość inna niż none
isolation: isolate
Stworzona dokładnie do tego celu, bez efektów ubocznych w wyglądzie
Wskazanie dowolnej właściwości, która po ustawieniu utworzyłaby kontekst nakładania
layout, paint lub skrót, który je zawiera (strict, content)
Top layer
Otwarty modalny dialog, popover, element pełnoekranowy oraz ich ::backdrop
Pułapka i rozwiązania
z-index 9999, który nadal przegrywa
Niebieska karta jest kontekstem z z-index 1. Jej tooltip ma 9999, ale jest porównywany tylko z elementami w karcie, więc pomarańczowy blok z z-index 2 go zakrywa.
isolation: isolate trzyma ujemną warstwę w środku
Bez isolate dekoracja z z-index: -1 spadłaby za tło sekcji i zniknęła. Z nim sekcja jest własnym kontekstem.
Sticky nagłówek z dropdownem
Nagłówek jest sticky, więc już jest kontekstem. Nadaj mu z-index wyższy niż treści, a dropdown w środku odziedziczy tę warstwę. Ogromne liczby nie są potrzebne.
Zwykła treść
Karty uniesione przy najechaniu, sticky nagłówki tabel
Menu, listy autouzupełniania
Sticky nagłówek strony
Tło pod szufladą
Własne modale (natywny dialog używa zamiast tego top layer)
Powiadomienia, które muszą być ponad wszystkim
Laboratorium nakładania z rozłożonym widokiem 3D
z-index nagłówka
z-index karty (lub auto)
z-index dropdownu
z-index banera
Wyzwalacz kontekstu na karcie
Dodatkowa właściwość na karcie
Rozłożony widok 3D (rozsuń warstwy)
Warstwy rozsunięte, wyżej oznacza malowane później
Płaski widok, prawdziwy CSS
Nagłówek z {z}
Karta z {z}
Dropdown z {z}
Baner z {z}
(w karcie)
nad banerem
pod banerem
Karta tworzy kontekst nakładania ({why}). Wartość {d} dropdownu liczy się tylko wewnątrz karty, więc jest on {pos}, bo tam jest karta.
Karta nie jest kontekstem nakładania, więc dropdown konkuruje bezpośrednio: {d} przeciwko {b} banera. Jest {pos}.
CSS dla tego układu
Kopiuj CSS
Spróbuj: karta z auto, dropdown 9999, potem wybierz transform. Jedna właściwość więzi dropdown.