Случвало ли ви се е да зададете z-index: 99999 на елемент във вашия CSS и той да не излиза върху други елементи? Толкова голяма стойност би трябвало лесно да постави този елемент визуално върху всичко останало, ако приемем, че всички различни елементи са зададени на по-ниска стойност или не са зададени изобщо. Една уеб страница обикновено се представя в двуизмерно пространство; въпреки това, чрез прилагане на специфични CSS свойства, се въвежда въображаема равнина на оста z, за да се предаде дълбочина. Тази равнина е перпендикулярна на екрана и от нея потребителят възприема реда на елементите един върху друг. Идеята зад въображаемата z-ос, възприятието на потребителя за подредени елементи, е, че CSS свойствата, които я създават, се комбинират, за да образуват това, което наричаме контекст на подреждане. Ще говорим за това как елементите са „подредени“ на уеб страница, какво контролира реда на подреждане и практически подходи за „отстраняване“ на елементи, когато е необходимо. Относно контекстите на подреждане Представете си вашата уеб страница като бюро. Докато добавяте HTML елементи, вие поставяте парчета хартия едно след друго на бюрото. Последният поставен лист е еквивалентен на най-скоро добавения HTML елемент и се намира върху всички други документи, поставени преди него. Това е нормалният документен поток, дори за вложени елементи. Самото бюро представлява основния контекст на подреждане, формиран от елемента , който съдържа всички останали папки. Сега влизат в действие конкретни свойства на CSS. Свойства като позиция (с z-индекс), непрозрачност, трансформиране и съдържане) действат като папка. Тази папка взема елемент и всички негови деца, извлича ги от основния стек и ги групира в отделен подстек, създавайки това, което наричаме контекст на стек. За позиционирани елементи това се случва, когато декларираме стойност на z-индекс, различна от auto. За свойства като непрозрачност, трансформация и филтър, контекстът на подреждане се създава автоматично, когато се прилагат конкретни стойности.
Опитайте се да разберете това: след като лист хартия (т.е. дъщерен елемент) е вътре в папка (т.е. контекст на подреждане на родителя), той никога не може да излезе от тази папка или да бъде поставен между документи в друга папка. Неговият z-индекс вече е уместен само в собствената му папка.
На илюстрацията по-долу хартия B вече е в контекста на подреждане на папка B и може да бъде поръчана само с други документи в папката.
Представете си, ако искате, че имате две папки на бюрото си:
.folder-a {z-индекс: 1; } .folder-b { z-индекс: 2; }
Нека актуализираме малко маркировката. Вътрешната папка A е специална страница, z-индекс: 9999. Вътрешната папка B е обикновена страница, z-индекс: 5.
.специална страница { z-индекс: 9999; } .plain-page { z-index: 5; }
Коя страница е отгоре? Това е .plain-страницата в папка B. Браузърът игнорира дъщерните документи и подрежда първо двете папки. Той вижда папка B (z-индекс: 2) и я поставя върху папка A (z-индекс: 1), защото знаем, че две е по-голямо от едно. Междувременно страницата .special-page, зададена на z-index: 9999, е в дъното на стека, въпреки че нейният z-index е зададен на най-високата възможна стойност. Контекстите за подреждане могат също да бъдат вложени (папки в папки), създавайки „родословно дърво“. Прилага се същият принцип: едно дете никога не може да избяга от папката на родителите си. Сега, след като разбирате как контекстите на подреждане се държат като папки, които групират и пренареждат слоевете, струва си да се запитате: защо определени свойства – като transform и opacity – създават нови контексти на подреждане? Ето нещо: тези свойства не създават контексти за подреждане поради начина, по който изглеждат; те го правят заради това как браузърът работи под капака. Когато приложите трансформация, непрозрачност, филтър или перспектива, вие казвате на браузъра: „Хей, този елемент може да се движи, завърта или избледнява, така че бъдете готови!“
Когато използвате тези свойства, браузърът създава нов контекст на подреждане, за да управлява изобразяването по-ефективно. Това позволява на браузъра да обработва независимо анимации, трансформации и визуални ефекти, като намалява необходимостта от преизчисляване на начина, по който тези елементи взаимодействат с останалата част от страницата. Представете си това като браузъра, който казва: „Ще се справя с тази папка отделно, така че да не се налага да размествам отново цялото бюро всеки път, когато нещо вътре в него се промени.“ Но имастраничен ефект. След като браузърът повдигне елемент в неговия собствен слой, той трябва да „изравни“ всичко в него, създавайки нов контекст на подреждане. Това е като да вземете папка от бюрото, за да я обработвате отделно; всичко вътре в тази папка се групира и браузърът вече го третира като едно цяло, когато решава какво да стои над какво. So even though the transform and opacity properties might not appear to affect the way that elements stack visually, they do, and it’s for performance optimisation. Няколко други свойства на CSS също могат да създават контексти за подреждане по подобни причини. MDN предоставя пълен списък, ако искате да копаете по-дълбоко. There are quite a few, which only illustrates how easy it is to inadvertently create a stacking context without knowing it. Проблемът с „разглобяването“. Проблеми с подреждането могат да възникнат по много причини, но някои са по-чести от други. Modal components are a classic pattern because they require toggling the component to “open” on a top layer above all other elements, then removing it from the top layer when it is “closed.” I’m pretty confident that all of us have run into a situation where we open a modal and, for whatever reason, it doesn’t appear. It’s not that it didn’t open properly, but that it is out of view in a lower layer of the stacking context. Това ви кара да се чудите "как така?" тъй като сте задали:
.overlay { position: fixed; /* създава контекста на подреждане */ z-индекс: 1; /* puts the element on a layer above everything else */ inset: 0; ширина: 100%; височина: 100vh; преливане: скрито; цвят на фона: #00000080; }
This looks correct, but if the parent element containing the modal trigger is a child element within another parent element that’s also set to z-index: 1, that technically places the modal in a sublayer obscured by the main folder. Нека да разгледаме този конкретен сценарий и няколко други често срещани клопки в контекста на подреждането. Мисля, че ще видите не само колко лесно е да създавате по невнимание контексти за подреждане, но и как да ги управлявате неправилно. Освен това как ще се върнете към управлявано състояние зависи от ситуацията. Сценарий 1: Модалът в капан
You can immediately see your modal trapped in a low-level layer and identify the parent. Browser Extensions Интелигентните разработчици са създали разширения, за да помогнат. Tools like this “CSS Stacking Context Inspector” Chrome extension add an extra z-index tab to your DevTools to show you information about elements that create a stacking context.
IDE Extensions You can even spot issues during development with an extension like this one for VS Code, which highlights potential stacking context issues directly in your editor.
Демонтиране и възстановяване на контрола След като идентифицираме основната причина, следващата стъпка е да се справим с нея. Има няколко подхода, които можете да предприемете, за да се справите с този проблем и ще ги изброя по ред. Можете обаче да изберете всеки на всяко ниво; никой не може да се оплаква или да пречи на друг. Промяна на HTML структурата Това се счита за оптималното решение. За да се натъкнете на проблем с контекста на подреждане, трябва да сте поставили някои елементи на смешни позиции във вашия HTML. Преструктурирането на страницата ще ви помогне да промените формата на DOM и да премахнете проблема с контекста на подреждането. Намерете проблемния елемент и го премахнете от прихващащия елемент в HTML маркирането. For instance, we can solve the first scenario, “The Trapped Modal,” by moving the .modal-container out of the header and placing it in the
element by itself.Това съдържание има z-индекс 2 и пак няма да покрие модала.Header
Main Content
When you click the “Open Modal” button, the modal is positioned in front of everything else as it’s supposed to be. See the Pen Scenario 1: The Trapped Modal (Solution) [forked] by Shoyombo Gabriel Ayomide. Adjust TheРодителски контекст на подреждане в CSS Ами ако елементът е такъв, който не можете да преместите, без да нарушите оформлението? По-добре е да се обърне внимание на проблема: родителят установява контекста. Намерете CSS свойството (или свойствата), отговорно за задействането на контекста, и го премахнете. Ако има цел и не може да бъде премахнат, дайте на родителя по-висока стойност на z-индекс от неговите събратящи елементи, за да повдигне целия контейнер. При по-висока стойност на z-индекс родителският контейнер се премества в горната част и неговите деца изглеждат по-близо до потребителя. Въз основа на това, което научихме в сценария „Потопеното падащо меню“, не можем да преместим падащото меню извън навигационната лента; няма да има смисъл. Можем обаче да увеличим стойността на z-index на контейнера .navbar, за да бъде по-голяма от стойността на z-index на елемента .content. .navbar { фон: #333; /* z-индекс: 1; */ z-индекс: 3; позиция: роднина; }
С тази промяна .dropdown менюто вече се показва пред съдържанието без проблем.
Вижте сценарий 2 на писалката: Потопеното падащо меню (решение) [форкнато] от Shoyombo Gabriel Ayomide.
Опитайте с портали, ако използвате рамка
В рамки като React или Vue, порталът е функция, която ви позволява да визуализирате компонент извън неговата нормална родителска йерархия в DOM. Порталите са като устройство за телепортиране на вашите компоненти. Те ви позволяват да визуализирате HTML на компонент навсякъде в документа (обикновено направо в document.body), като същевременно го поддържате логически свързан с оригиналния му родител за подпори, състояние и събития. Това е идеално за избягване на капаните на контекста на подреждане, тъй като изобразеният изход буквално се появява извън проблемния родителски контейнер.
ReactDOM.createPortal(
Това гарантира, че падащото ви съдържание не е скрито зад своя родител, дори ако родителят има препълване: скрито или по-нисък z-индекс. В сценария „The Clipped Tooltip“, който разгледахме по-рано, използвах портал, за да спася подсказката от препълването: скрит клип, като го поставих в тялото на документа и го позиционирах над тригера в контейнера. Вижте Сценарий 3 на писалката: Изрязаната подсказка (решение) [разклонена] от Shoyombo Gabriel Ayomide. Представяме ви контекст на подреждане без странични ефекти Всички подходи, обяснени в предишния раздел, са насочени към „демонтиране“ на елементи от проблемни контексти на подреждане, но има някои ситуации, в които наистина ще имате нужда или искате да създадете контекст на подреждане. Създаването на нов контекст на подреждане е лесно, но всички подходи идват със страничен ефект. Тоест, с изключение на използването на изолация: изолирайте. Когато се прилага към елемент, контекстът на подреждане на децата на този елемент се определя спрямо всяко дете и в рамките на този контекст, вместо да се влияе от елементи извън него. Класически пример е присвояването на този елемент на отрицателна стойност, като z-index: -1. Представете си, че имате компонент .card. Искате да добавите декоративна форма, която стои зад текста на .card, но върху фона на картата. Без контекст на подреждане на картата, z-index: -1 изпраща формата в долната част на основния контекст на подреждане (цялата страница). Това го кара да изчезне зад белия фон на .card: Вижте Pen Negative z-index (проблем) [forked] от Shoyombo Gabriel Ayomide. За да разрешим това, ние декларираме isolation: isolate на родителската .card: Вижте Pen Negative z-index (решение) [forked] от Shoyombo Gabriel Ayomide. Сега самият елемент .card става контекст за подреждане. Когато дъщерният му елемент — декоративната форма, създадена върху псевдо-елемента :before — има z-индекс: -1, той отива в най-долната част на контекста на подреждане на родителя. Той стои идеално зад текста и върху фона на картата, както е предвидено. Заключение Запомнете: следващия път, когато вашият z-индекс изглежда извън контрол, това е уловен контекст на подреждане. Референции
Контекст на подреждане (MDN) Z-индекс и контексти на подреждане (web.dev) „Как да създадем нов контекст на подреждане със свойството Isolation в CSS“, Натали Пина „Какво по дяволите, z-индекс??“, Джош Комо
Допълнителна информация за SmashingMag
„Управление на CSS Z-индекс в големи проекти“, Стивън Фрийсън „Лепкави заглавки и елементи с пълна височина: сложна комбинация“, Филип Браунен „Управление на Z-индекс в уеб приложение, базирано на компоненти“, Павел Померанцев „Свойството CSS на Z-индекс: Изчерпателен поглед“, Луис Лазарис