Урок 19. Теория: z-index и контекст наложения (stacking context)

📁 Раздел: Блочная модель и позиционирование ⏱️ Время изучения: ~50 мин 🎯 Сложность: Средняя
#z-index #position #opacity #transform #isolation

⚡ Кратко

z-index управляет слоями только внутри правил наложения. Главное — понять stacking context: локальный мир слоёв, где большое число не может перепрыгнуть наружу.

Главная идея

Пока элементы не перекрываются, порядок слоёв не важен. Но как только блоки накладываются друг на друга (через position, отрицательные отступы, наложение), возникает вопрос: кто окажется сверху? За это отвечает третья ось — ось z, направленная «из экрана к зрителю». Свойство z-index двигает элемент вдоль неё.

Ключевой и неочевидный момент: z-index — это не абсолютная высота элемента над всей страницей. Число сравнивается только с «соседями» внутри одного контекста наложения (stacking context). Контекст — это локальный «мир слоёв»: потомки внутри него сортируются между собой, но во внешний мир весь контекст выходит как один слой. Поэтому ребёнок с z-index: 9999 не перепрыгнет чужой блок, если его родитель «заперт» в своём контексте с маленьким числом.

Представьте многоэтажный дом. Этаж — это контекст наложения, а квартиры на этаже — элементы внутри него. Можно бесконечно нумеровать квартиры (101, 999, 9999) — но квартира на 2-м этаже всё равно ниже любой квартиры 3-го этажа. Номер квартиры (z-index) решает порядок только внутри своего этажа. Чтобы подняться выше соседнего блока, нужно сменить этаж — то есть выйти из своего контекста наложения, а не наращивать число.

Как работает: порядок слоёв по оси z

В пределах одного контекста браузер раскладывает элементы примерно в таком порядке (снизу вверх): фон контекста → блоки с отрицательным z-index → обычный поток → плавающие элементы → строчный контент → позиционированные элементы с z-index: auto/0 → элементы с положительным z-index. Схематично ось z выглядит так:

z-index: 1 z-index: 2 z-index: 3 ближе к зрителю
Чем больше z-index, тем ближе слой к зрителю — но только в пределах одного контекста наложения.
Проверить по документации: stacking context создаётся не только связкой position + z-index. Новый контекст порождают также opacity меньше 1, любой transform/filter/perspective, isolation: isolate, will-change, элементы внутри flex/grid с заданным z-index и др. Полный и актуальный список — в MDN «Stacking context».

Базовый пример: бейдж поверх картинки

Чтобы бейдж лёг поверх изображения, оба должны быть позиционированы (без position z-index игнорируется), а бейдж получает большее число.

ХИТ
📄 lesson-19/card.css
.card  { position: relative; }
.badge {
  position: absolute;
  top: 8px; right: 8px;
  z-index: 2;   /* поверх картинки */
}

Когда применять

z-index нужен везде, где элементы намеренно перекрываются: бейджи и метки на карточках, выпадающие меню, всплывающие подсказки, «липкие» шапки, модальные окна с затемнением, тосты-уведомления. Хорошая практика — не плодить случайные числа, а завести единую шкалу слоёв (base → dropdown → sticky → overlay → modal → toast) и хранить её в CSS-переменных.

Частая ошибка: ребёнок не может перепрыгнуть соседа

Самая болезненная ловушка: вы ставите ребёнку z-index: 9999, а он всё равно под соседним блоком. Причина — родитель создал свой stacking context (например, transform или opacity), и весь ребёнок «заперт» внутри него. Сравнивается не 9999 с соседом, а контекст родителя с соседом.

  1. Сначала найдите позиционирование: position и offsets (top/right/bottom/left).
  2. Поднимитесь по родителям и проверьте, кто создаёт контекст (transform, opacity<1, filter, isolation).
  3. Сравнивайте z-index только среди элементов одного контекста.
  4. Если элемент не поднимается — чините не число, а границу контекста (выносите элемент выше по дереву или поднимайте сам родитель).
Инструмент: в Chrome DevTools на вкладке Layers видно реальные слои композитинга, а в инспекторе у элемента можно увидеть пометку, что он создаёт stacking context.

Навигация