Перейти к содержанию

Контексты наложения

Когда два элемента перекрываются, кажется естественным дать нужному элементу очень большой z-index. Однако это число сравнивается не со всеми числами страницы одновременно. Контекст наложения объединяет часть дерева в самостоятельную группу, и её потомки не выходят из группы лишь за счёт собственного большого значения. Для понимания результата нужно рассматривать уровни, на которых находятся конкурирующие коробки.

В прошлом уроке появилась абсолютная метка карточки. Сейчас сохраним каталог и добавим отдельный диагностический блок ниже списка. Он не станет постоянным украшением интерфейса: следующий урок удалит его после разбора. Результат — объяснимое перекрытие двух панелей и метки внутри первой панели.

Два соседних контекста

В index.html вставьте следующий полный блок перед секцией учебной заявки. Это самостоятельная лаборатория внутри той же страницы; заголовок и его идентификатор не совпадают с идентификаторами каталога. Курсы и их реальные ссылки не изменяются.

<section class="lab-stack-lab" aria-labelledby="stack-title">
<h2 id="stack-title">Опыт с наложением</h2>
<div class="stack-stage">
<div class="stack-panel stack-panel--a">Панель A<span class="stack-label">Метка A: z-index 99</span>
</div>
<div class="stack-panel stack-panel--b">Панель B: z-index 2</div>
</div>
<p>Диагностический блок: метка принадлежит контексту панели A.</p>
</section>

В конец styles.css добавьте следующий блок. Классы диагностического опыта отдельные, поэтому он не меняет положение настоящих карточек.

@layer components {
.layout-lab .lab-stack-lab { margin-block-start: 2rem; }
.layout-lab .stack-stage { display: grid; grid-template-columns: 1fr 1fr; min-block-size: 9rem; isolation: isolate; margin-block: 1rem; }
.layout-lab .stack-panel { position: relative; padding: 1rem; }
.layout-lab .stack-panel--a { z-index: 1; background: #443563; }
.layout-lab .stack-panel--b { z-index: 2; background: #284c35; }
.layout-lab .stack-label { position: absolute; z-index: 99; inset-block-start: 3rem; inset-inline-start: 75%; inline-size: 12rem; padding: .5rem; background: #9162cd; color: #fff; }
}

Ожидаются две соседние панели. Метка A начинается возле правой части первой панели и выходит в область второй. Несмотря на своё значение девяносто девять, пересекающаяся часть метки ожидается под панелью B с числом два. Причина не в том, что число девяносто девять мало, а в принадлежности метки контексту A.

Панель A позиционирована и имеет z-index: 1, поэтому создаёт собственный контекст. Панель B с z-index: 2 создаёт соседний. На уровне их общего родителя сравниваются эти два контекста. Вся группа A оказывается ниже группы B, а внутреннее число метки определяет её положение только внутри A. Внутренний порядок нельзя использовать как пропуск через границу родительского контекста.

Проверка уровня сравнения

Для первого временного опыта измените у панели A z-index: 1 на 3. Ожидается, что весь её контекст будет выше B, а пересекающаяся часть метки станет видимой поверх B. Затем верните исходную единицу. Мы поменяли положение группы, а не внутренний номер метки, поэтому результат объясняется на нужном уровне дерева.

Для второго отдельного опыта верните исходное состояние и замените только z-index панели A на auto. При сохранённой структуре собственного контекста от этого объявления у A уже не будет. Метка с заданным положением и числом сможет участвовать в контексте более высокого уровня. Такой опыт показывает, что значение auto не является просто новым числом, равным нулю, с теми же последствиями для группировки.

После обоих наблюдений восстановите основной снимок: A равна единице, B — двум, метка — девяносто девяти. Диагностические изменения не складываются друг с другом. Если одновременно изменить A, добавить transform и поднять B, получится другой опыт, и уже нельзя будет объяснять результат единственной известной причиной.

Свойство isolation: isolate у площадки опыта создаёт внешний контекст и удерживает лабораторию в собственной группе относительно окружающей страницы. Оно не отменяет внутренних отношений A и B. Это удобно, чтобы учебная метка не соревновалась со случайной панелью другой секции. Локальная изоляция задаёт границу опыта, а не универсальный способ поднять все его элементы над интерфейсом.

Что ещё создаёт контекст

Контекст может появиться не только из пары position и числового z-index. Важны также некоторые эффекты оформления и компоновки, например opacity меньше единицы, transform и заданный z-index у Flex- или Grid-элемента. Поэтому добавление визуального эффекта к родителю иногда меняет поведение старого всплывающего потомка, хотя его собственный CSS не был отредактирован.

Это перечень причин для диагностики, а не предложение добавить все свойства сразу. В нашем основном опыте причина явно задана позиционированными панелями. Если вы разбираете настоящую страницу, просмотрите цепочку предков и найдите конкретную границу контекста. Полный актуальный список условий приведён в MDN о контекстах наложения.

Сам z-index также зависит от типа коробки. У обычного статичного блокового элемента запись большого числа обычно не создаёт ожидаемого подъёма. Grid- и Flex-элементы имеют собственные условия применения этого свойства. Поэтому инструкция «просто увеличьте число» скрывает сразу две предпосылки: элемент должен участвовать в подходящем механизме, а конкурирующий элемент должен находиться на сравнимом уровне.

Порядок наложения не меняет HTML-последовательность и фокус. Метка, нарисованная поверх кнопки, не перемещает кнопку в конец клавиатурного маршрута. Если видимая панель накрывает важное действие, проблема остаётся в интерфейсе даже при правильном вычислении контекстов. Мы сейчас предсказываем рисование, а не объявляем макет доступным после назначения нескольких чисел.

Слои каскада и слои рисования

Слои @layer из семнадцатого урока выбирают, какие CSS-значения победят. Контексты наложения определяют рисование коробок уже с выбранными значениями. Сходство слова «слой» не делает механизмы одним и тем же. Перенос правила в utilities может выбрать другое значение z-index, но не создаёт самостоятельного нового уровня рисования только из-за имени CSS-группы.

Также отличайте контекст наложения от браузерного слоя, который инструмент производительности может показать при компоновке и рисовании. Оптимизация движка и авторский порядок перекрытий имеют разные обязанности. Не обещайте ускорение по одному z-index или isolation и не считайте появление аппаратного слоя доказательством правильного визуального порядка. В этом уроке никаких измерений производительности не проводилось.

Позднее нативный модальный диалог будет попадать в top layer. Этот механизм отличается от попытки выдать обычной карточке огромное число. Его взаимодействие и фокус рассматриваются вместе с элементом dialog, поэтому сейчас не имитируем модальность нашей цветной лабораторией. Панели опыта являются обычным содержимым документа и не блокируют действия за собой.

Завершение диагностического опыта

Посмотрите на подпись первой панели как на содержимое родителя, а не отдельную независимую наклейку поверх всего сайта. Такая модель позволяет предсказать обе временные правки. Она особенно полезна при меню, подсказках и изображениях с эффектами: требуется найти границу группы, затем решить, должна ли она действительно ограничивать дочерний элемент.

Если метка нужна за пределами карточки, возможным решением бывает другая структура HTML или специальный нативный механизм. Простое повышение внутреннего числа проблему границы не решает. Однако переносить элемент в конец body без разбора тоже нельзя: поменяются его семантическая связь, координаты и обработка событий. Правильная структура зависит от конкретного действия.

Основной снимок этого урока сохраняет лабораторию для наблюдения. В следующем уроке полностью удалим секцию lab-stack-lab и её отдельные правила, оставив исходный каталог с меткой. Затем добавим локальную навигацию, которая временно закрепляется при прокрутке, сохраняя своё место в потоке.

Полное состояние этого шага находится в layout-lab/lesson-23 внутри исходников продолжения. Каждый снимок открывается отдельно; подключать CSS разных уроков одновременно не нужно.

Оглавление курса.