Ile warstw ma strona www?
Jaki z-index musi mieć modal, żeby był widoczny zawsze nad wszystkimi elementami? Większość frontend developerów ustawia wartość gdzieś pomiędzy 99999 a 99999999. A możemy udałoby zmieścić się w wartości poniżej 10. Poznaj stacking context - mechanizm CSSa, który warto znać.
Z tego artykułu dowiesz się:
Co to jest stacking context?
Dlaczego z-index: 999999; nie działa?
Ile jest sposobów na utworzenie nowego stacking context'u?
Za co odpowiada właściwość CSS isolation?
Spróbuj pomyśleć o dowolnej stronie internetowej. Masz? Super, więc zadam Ci teraz proste pytanie: w ilu wymiarach została zaprojektowana? Nie zdziwiłbym się, gdyby padła odpowiedź, że w dwóch. To, co widzimy jest przecież płaskie, elementy interfejsu są poukładane w pionie i w poziomie. A co jeśli Ci powiem, że to nie do końca prawda? Strony internetowe projektowane są zawsze w trzech wymiarach i nie dlatego, że takie jest widzimisię projektantów. Programy graficzne układają nowe elementy w sposób warstwowy. Podczas implementacji jest podobnie, ale wynika to z założeń CSS i jego mechanizmu, który nazywa się stacking context.
Trzeci wymiar
Ze szkoły podstawowej zapewne pamiętasz osie x, y i z. Każda z tych osi w układzie współrzędnych pozwala określić położenie punktu. Określenie tylko jednej wartości pozwala nam na umiejscowienie punktu na jednej płaszczyźnie. Aby wyznaczyć położenie elementu w przestrzeni musimy znać wszystkie 3 wartości. Pozwala nam to bardzo dokładnie określić co się dzieje z naszym punktem.
Wyobraź sobie, że elementy HTML strony internetowej układają się wzdłuż osi z skierowanej w stronę użytkownika, który aktualnie patrzy na tę stronę www. Można śmiało powiedzieć, że układają się w przestrzeni jak warstwy, zgodnie z kolejnością priorytetów, które zostały im nadane. Im element ma wyższy priorytet, tym bliżej jest użytkownika. Takie są ogólne założenia, w zasadzie gdyby na tym poprzestać byłoby to bardzo proste.
Struktura elementów z powyższego przykładu na osi z będzie zgodna z kolejnością renderowania elementów, czyli od góry do dołu. Element o klasie item-1
będzie położony najniżej, a item-3
znajdzie się najbliżej użytkownika.
Sytuacja skomplikuje się jednak, gdy elementy HTML będą miały swoje dzieci. Wówczas ich kolejność na naszej osi z już nie będzie taka oczywista, a zarządzanie nią może stać się nie lada wyzwaniem. Na szczęście w CSS istnieje mechanizm, który to porządkuje. Stacking context (w polskiej literaturze można znaleźć określenia: stos kontekstu, kontekst układania), bo to o nim mowa, pozwala na układanie i grupowanie elementów HTML, ustalając ich pozycję początkową w oparciu o element bazowy. Który element nim będzie? To zależy. Czasami będzie to bezpośredni rodzic, czasami root dokumentu, a czasami inny „wstępny” w strukturze.
Warto tutaj dodać, że w ramach naszej strony powstanie wiele takich kontekstów, każdy z nich będzie całkowicie niezależny od swojego rodzeństwa, każdy może zawierać się w innych kontekstach a jednocześnie razem będą tworzyć hierarchiczną strukturę, która będzie swoistym podzbiorem dla struktury całego dokumentu HTML. Ważne, aby zrozumieć w jakich sytuacjach powstaną i jak je wykorzystać, ewentualnie pokonać. Wiemy wszak, że z-index: 99999;
nie zawsze działa tak, jakbyśmy się tego spodziewali.
Niezrozumiany z-index
Do zarządzania stacking context’em służy właściwość css: z-index
. z-index
może przyjąć wartości liczbowe zarówno ujemne, jak i dodatnie. Oprócz tego może przyjąć wartość auto
, która domyślnie ustawiona jest na 0 i, co ważne, nie spowoduje utworzenia nowego „stosu kontekstu”. Wartość auto
jest domyślna. Zatem dodanie do z-index
auto
lub po prostu, go pomięcie, spowoduje, że elementy zostaną ustawione tak, jak wynikać to będzie ze struktury dokumentu HTML. W powyższym akapicie zastosowałem kilka uproszczeń, ale poniżej je doprecyzuję.
Ustawienie wartości liczbowej natomiast taki nowy kontekst zainicjuje, ale czy zawsze? Byłoby zbyt prosto, gdyby tak było. Tutaj dochodzimy do 13 przypadków, kiedy stacking context zostanie ustanowiony.
13 przypadków, które warto znać
Jak już wiemy samo ustawienie z-index
nie wygeneruje nam nowego kontekstu. Jak wspomniałem, elementy zostaną umiejscowione jako warstwy w ramach najbliższego istniejącego stacking context’u. Oczywiście będziemy przeszukiwać hierarchię w górę drzewa, a gdy nie znajdziemy żadnego kontekstu dojdziemy do root’a naszego dokumentu, czyli w większości przypadków elementu <html>
. To jest nasz pierwszy przypadek.
Stacking context tworzony jest zawsze dla root’a dokumentu.
Kolejne dwa przypadki dotyczą połączenia z-index
oraz właściwości position
. Domyślnie wszystkie elementy HTML mają pozycję statyczną (static
). Zmieniając pozycję na relatywną (relative
) lub absolutną (absolute
) i ustawiając z-index
jako wartość liczbową wyodrębnimy nowy kontekst.
W przypadku ustawienia pozycji jako fixed
lub sticky
, nie musimy dodawać z-index
, aby powstał nowy stacking context. On powstanie prawie zawsze - wyjątkiem będzie właściwość sticky na starszych przeglądarkach desktopowych (na mobilnych nie będzie wyjątku).
Czwarty i piąty przypadek to połączenie właściwości display: flex;
lub display: grid;
z z-index
. Szósty to ustawienie wartości mniejszej niż 1 dla właściwości opacity
. Siódmy przypadek to użycie którejś z właściwości: transform
, filter
, backdrop-filter
, perspective
, clip-path
, mask
, mask-image
lub mask-border
z wartością inną niż none
.
Pierwsze siedem przypadków jest dość popularnych i dlatego dość łatwo je zapamiętać. Kolejne 5 zasad, które utworzą nam nowy stacking context to:
właściwość
container-type
z wartościąsize
lubinline-size
w container query (@container
),właściwość
mix-blend-mode
z wartością inną niżnormal,
właściwość
isolation
z wartościąisolate
,właściwość
contain
z wartościąlayout
lubpaint
, lub z wartościami złożonymi zawierającymi jedną z nich jak:content
czystrict,
właściwość
will-change
, która jako wartość wskazała jakąkolwiek z właściwości, które powodują tworzenie nowych kontekstów.
Ostatni przypadek jest ciekawy. Dotyczy elementów, które znajdują się na najwyższej warstwie dokumentu oraz obejmują całą wysokość i szerokość wyświetlanego obszaru (tj. viewport’u). Elementy, które umieszczone zostaną w tej warstwie utworzą nowy kontekst wraz z odpowiadającymi im pseudo-elementami ::backdrop
.
Spójrzmy na poniższy przykład, aby zrozumieć co się dzieje, gdy powstaje nowy kontekst.
Zasadniczo najwyższy z-index
ma element o klasie modal. Jeśli spojrzymy na strukturę naszego dokumentu, to znajduje się on w elemencie <main>
. Element <main>
nie tworzy nowego kontekstu, ale poprzez to, że posiada pozycję relatywną pozwala nam na manipulowanie położeniem modela względem <main>
. Biorąc powyższe pod uwagę nasz modal został przypisany do stacking context’u, który został utworzony na głównym elemencie, czyli na <html>
. W tym samym kontekście jest umieszczony również <header>
. Porównując wartości z-index
obu elementów, od razu widać, że modal powinien być nad wszystkim. I rzeczywiście tak jest.
Sytuacja zmieni się diametralnie, gdy w <main>
utworzymy nowy stacking context o niższym z-index
niż ma <header>
.
W naszym przykładzie dodanie właściwości filter
tworzy nowy stacking context, który ma niższy priorytet niż <header>
i umieszcza go na naszej osi z pod nim. Co ostatecznie powoduje, że nasz modal, pomimo posiadania zdecydowanie wyższego z-index
, znajduje się pod nagłówkiem.
Warto też dodać, że zgodnie z ogólnymi założeniami z-index
, aby zadziałał będzie potrzebował innej pozycji niż statyczna. Ta zasada ma jednak swój wyjątek - dotyczy elementów potomnych dla flexbox’a. Dzieci flexbox’a mogą używać z-index nawet, gdy mają pozycję statyczną.
Siła izolacji
Przypadków tworzenia stacking context w ramach strony www jest sporo. Większość z nich powoduje dodanie różnego rodzaje efektów ubocznych (takich jak transformacje czy zmiana sposobu wyświetlania elementów) oprócz tworzenia nowego kontekstu.
Świadome tworzenie kontekstów w ramach aplikacji internetowej może być bardzo wartościowe, ponieważ pozwala nam dokonywać wyboru nad kolejnością warstw i unikać pomyłek, których naprawienie w przyszłości może być kosztowne. W momencie, gdy chcemy utworzyć nowy stacking context i nic więcej, możemy skorzystać z niedocenianej i prawdopodobnie mało znanej właściwości isolation: isolate
. Jedyną rzecz, którą wykona ta operacja, będzie utworzenie nowego contextu, tam gdzie nie powstał w wyniku innych działań.
Podsumowanie
CSS jest specyficznym językiem. Z jednej strony jest bardzo prosty i wydaje się być intuicyjny, ale posiada również wiele mechanizmów, których wcale nie musimy znać, aby w nim pisać. Pozornie możemy całe lata tworzyć kod i nie być świadomymi tego, jak on naprawdę działa. Dopiero zgłębienie tematu przy okazji „dziwnych bug'ów” pomaga nam lepiej opanować ten obszar. CSS jest też o tyle trudnym językiem, że praktycznie nie zwraca on programistom żadnej informacji o błędach, ostrzeżeniach itp. Jest jak z gumy. Co zrobimy to będzie działać, jakoś. Można się do niego przez to szczerze zniechęcić.
Stacking context to jeden z takich ukrytych mechanizmów. Poznanie i opanowanie go pozwoli nam na świadome używanie właściwości z-index
, bez dziwnych zabiegów w rodzaju: z-index: 999999;
.
Komentarze (0)
Jeszcze nikt nic nie napisał, ale to znaczy że... możesz być pierwszy/pierwsza.