z-index
z-indexуправляет порядком наложения элементов по оси Z (глубина). Работает только на позиционированных элементах (position!=static). Ключевая концепция — stacking context (контекст наложения).
Зачем нужно
Когда элементы перекрываются (модальные окна, выпадающие меню, тултипы, фиксированные шапки), z-index определяет, какой элемент окажется сверху. Без понимания stacking context невозможно отладить проблемы наложения.
Где используется
- Модальные окна и оверлеи
- Выпадающие меню и тултипы
- Фиксированные шапки и sidebar
- Toast-уведомления
- Sticky-элементы
Предпосылки
Базовый синтаксис
.below { position: relative; z-index: 1; }
.above { position: relative; z-index: 2; } /* Сверху */
/* Значения */
.auto { z-index: auto; } /* Не создаёт stacking context */
.zero { z-index: 0; } /* Создаёт stacking context */
.neg { z-index: -1; } /* Ниже нормального потока */
.high { z-index: 9999; } /* Высокий приоритет */
z-indexработает только приposition: relative | absolute | fixed | stickyили в flex/grid-потомках.
Stacking Context (контекст наложения)
Stacking context — это «слой», внутри которого z-index действует локально. Элемент с z-index: 999 внутри контекста с z-index: 1 не перекроет элемент с z-index: 2 вне этого контекста.
Что создаёт новый stacking context
/* 1. position + z-index */
.ctx1 { position: relative; z-index: 0; }
/* 2. position: fixed или sticky (всегда) */
.ctx2 { position: fixed; }
/* 3. opacity < 1 */
.ctx3 { opacity: 0.99; }
/* 4. transform */
.ctx4 { transform: translateZ(0); }
/* 5. filter */
.ctx5 { filter: blur(0); }
/* 6. will-change */
.ctx6 { will-change: transform; }
/* 7. isolation: isolate */
.ctx7 { isolation: isolate; }
/* 8. contain: layout или paint */
.ctx8 { contain: paint; }
/* 9. mix-blend-mode */
.ctx9 { mix-blend-mode: multiply; }
/* 10. Flex/Grid потомок с z-index */
.flex-container { display: flex; }
.flex-container > .ctx10 { z-index: 1; }
Визуализация проблемы
<div class="parent-a" style="position: relative; z-index: 1;">
<div class="child" style="position: absolute; z-index: 999;">
Я z-index: 999, но внутри контекста с z-index: 1
</div>
</div>
<div class="parent-b" style="position: relative; z-index: 2;">
Я z-index: 2, и я СВЕРХУ child с z-index: 999!
</div>
Порядок наложения (Stacking Order)
Внутри одного stacking context элементы располагаются в таком порядке (снизу вверх):
- Фон и границы элемента-контекста
- Потомки с отрицательным
z-index - Блочные элементы в потоке (не позиционированные)
- Float-элементы
- Inline-элементы в потоке
- Позиционированные с
z-index: autoилиz-index: 0 - Потомки с положительным
z-index
/* Элементы без z-index сортируются по порядку в DOM */
/* Последний в HTML — сверху */
Система z-index токенов
Для больших проектов — централизованная шкала:
:root {
--z-dropdown: 100;
--z-sticky: 200;
--z-fixed: 300;
--z-modal-backdrop: 400;
--z-modal: 500;
--z-popover: 600;
--z-tooltip: 700;
--z-toast: 800;
}
.dropdown { z-index: var(--z-dropdown); }
.header { z-index: var(--z-fixed); }
.modal-bg { z-index: var(--z-modal-backdrop); }
.modal { z-index: var(--z-modal); }
.tooltip { z-index: var(--z-tooltip); }
.toast { z-index: var(--z-toast); }
isolation: isolate
Создаёт stacking context без побочных эффектов:
/* Изолировать компонент — его z-index не повлияет на внешний мир */
.component {
isolation: isolate;
}
/* Внутри компонента z-index работает локально */
.component .overlay {
position: absolute;
z-index: 10; /* Только внутри .component */
}
isolation: isolate— лучший способ создать stacking context, не меняяopacity,transformи т.д.
Отладка z-index
DevTools
- Chrome: Elements → Computed → ищи
z-index - Firefox: Layout → Stacking Context (показывает дерево контекстов)
- 3D View: Chrome DevTools → More tools → Layers
Чеклист при проблемах
- Есть ли
position!=static? - Не создал ли предок новый stacking context?
- Какие z-index у конкурирующих элементов?
- Не ограничивает ли
overflow: hiddenвидимость?
/* Отладочный приём — подсветить все stacking contexts */
* {
outline: 1px solid rgba(255, 0, 0, 0.2);
}
[style*="z-index"],
[class] {
outline: 2px solid red;
}
Частые ошибки
-
z-index без position — не работает:
/* НЕ РАБОТАЕТ */ .box { z-index: 100; } /* РАБОТАЕТ */ .box { position: relative; z-index: 100; } -
«Война z-index» —
z-index: 999999вместо понимания stacking context:/* ПЛОХО */ .modal { z-index: 999999; } .tooltip { z-index: 9999999; } /* ХОРОШО — используйте токены */ .modal { z-index: var(--z-modal); } .tooltip { z-index: var(--z-tooltip); } -
Неожиданный stacking context от opacity/transform — элемент с
opacity: 0.99создаёт новый контекст -
z-index на flex-потомке без position — работает! Но неожиданно для многих:
.flex-parent { display: flex; } .flex-child { z-index: 1; } /* Работает без position! */ -
Отрицательный z-index уходит за фон родителя — если у родителя нет stacking context:
.child { position: relative; z-index: -1; } /* За фоном родителя! */ /* Решение: isolation: isolate на родителе */
Практика
- Создать 3 перекрывающихся блока и управлять порядком через z-index
- Воспроизвести проблему stacking context (z-index: 999 не работает)
- Реализовать систему z-index токенов
- Использовать
isolation: isolateдля компонента - Отладить z-index через Firefox Layout panel
Связанные темы
- Position — position: relative/absolute/fixed/sticky
- Display — flex/grid и z-index потомков
- transition -- плавные переходы — анимация z-index (целые числа)