Вы задали элементу z-index: 999, а он все равно прячется под соседним блоком. Вы добавляете position: relative, играете с числами — а толку ноль. Знакомо? Это мои будни еще пару лет назад. Все изменилось, после того как я понял как работает контекст наложения — правило, которое объясняет, почему порядок слоев работает не так, как вы думаете.
- Что такое контекст наложения (Stacking Context)
- Как браузер раскладывает страницу по оси Z (базовый порядок)
- Что создает новый контекст наложения?
- 1. position + z-index
- 2. position: fixed или sticky (даже без z-index)
- 3. opacity < 1
- 4. transform, filter, perspective
- 5. will-change
- 6. display: flex / grid + z-index на дочерних элементах
- 7. mix-blend-mode, isolation
- 8. container-type
- 9. Другие свойства
- Как работает z-index внутри одного контекста
- Почему z-index не работает (главные ошибки)
- Ошибка 1: Элементы в разных контекстах
- Ошибка 2: Родительский контекст перекрывает всё
- Ошибка 3: position: static (без позиционирования)
- Принудительное создание контекста (isolation)
- Итоги
Что такое контекст наложения (Stacking Context)
Контекст наложения — это концепция, с помощью которой браузер определяет порядок отображения элементов вдоль оси Z (перпендикулярно экрану). Она определяет, какой слой окажется выше или ниже при перекрытии.
Контекст наложения на странице чаще всего не один. При этом каждый контекст наложения — это отдельная вселенная со своим порядком слоев. Элементы из разных контекстов не конкурируют друг с другом по z-index.
Представить это можно как стол с нагромождением посуды. Если убрать часть посуды на другой стол (создать новый контекст наложения), она перестает «конкурировать» за вертикальное пространство с посудой с первого стола.
Как браузер раскладывает страницу по оси Z (базовый порядок)
Без учета контекстов наложения браузер рисует слои в таком порядке:
- Фон и границы корневого элемента (
<html>) - Элементы с отрицательным
z-index(в порядке появления) - Блоки без позиционирования (статичные и относительные без
z-index) - Элементы с
position: relative/absolute/fixed/stickyиz-index: auto(в порядке появления) - Элементы с положительным
z-index(в порядке возрастания)
Что создает новый контекст наложения?
Новый контекст наложения создается, когда элемент выходит из потока или получает определенные CSS-свойства.
1. position + z-index
.element {
position: relative; /* или absolute, fixed, sticky */
z-index: 5; /* любое число, кроме auto */
}
2. position: fixed или sticky (даже без z-index)
.element {
position: fixed; /* всегда создает контекст */
}
3. opacity < 1
.element {
opacity: 0.99; /* любое значение меньше 1 */
}
4. transform, filter, perspective
.element {
transform: scale(1.1);
/* или */
filter: blur(5px);
/* или */
perspective: 500px;
}
5. will-change
.element {
will-change: transform; /* если создает контекст в браузере */
}
6. display: flex / grid + z-index на дочерних элементах
Если у родителя display: flex или display: grid, а у дочернего элемента есть z-index (не auto), то родитель создает контекст наложения.
.parent {
display: flex;
}
.child {
z-index: 1; /* родитель создает контекст */
}
7. mix-blend-mode, isolation
.element {
isolation: isolate; /* принудительно создает контекст */
}
8. container-type
.element {
container-type: inline-size;
}
9. Другие свойства
backdrop-filtermaskclip-path(не все браузеры)z-indexуposition: sticky
Как работает z-index внутри одного контекста
Внутри одного контекста z-index работает как ожидается:
<div class="parent">
<div class="child1" style="z-index: 10">Я сверху</div>
<div class="child2" style="z-index: 5">Я снизу</div>
</div>
child1 будет поверх child2, потому что они в одном контексте наложения (у родителя нет свойств, создающих контекст).
Почему z-index не работает (главные ошибки)
Ошибка 1: Элементы в разных контекстах
<div style="position: relative; z-index: 1">
<div style="position: absolute; z-index: 100">Я внутри контекста A</div>
</div>
<div style="position: relative; z-index: 2">
<div style="position: absolute; z-index: 1">Я внутри контекста B</div>
</div>
Хотя z-index: 100 больше, чем z-index: 1, второй элемент может оказаться сверху, потому что родитель с z-index: 2 создает новый контекст, и его дочерние элементы соревнуются только внутри этого контекста.
Решение: Убрать z-index у родителя, если он не нужен.
Ошибка 2: Родительский контекст перекрывает всё
<div style="position: relative; z-index: 1">
<!-- Все дочерние элементы будут под элементами с z-index > 1 на том же уровне -->
<div style="position: absolute; z-index: 999">Я все равно под вторым блоком</div>
</div>
<div style="position: relative; z-index: 2">
Я сверху, потому что родительский z-index больше
</div>
Решение: Поднять z-index у родителя, а не у дочернего элемента.
Ошибка 3: position: static (без позиционирования)
/* ❌ z-index не работает без position */
.element {
z-index: 10;
}
/* ✅ Нужно добавить position (кроме static) */
.element {
position: relative;
z-index: 10;
}
Принудительное создание контекста (isolation)
Если вам нужно «отрезать» элемент от родительского контекста, используйте isolation: isolate:
.modal {
isolation: isolate;
position: fixed;
z-index: 1000;
}
Теперь модальное окно создает свой контекст наложения, и его дочерние элементы не будут конфликтовать с остальной страницей.
Итоги
- Контекст наложения — это изолированное пространство, в котором действует
z-index - Элементы из разных контекстов не конкурируют по
z-index. Порядок определяется родительскими контекстами. - Новый контекст создают:
position+z-index(кромеauto),position: fixed,opacity < 1,transform,filter,flex/gridс дочернимz-index,isolation: isolateи многие другие. - Если
z-indexне работает — скорее всего, элемент в другом контексте.
Главное, что нужно запомнить: z-index: 9999 не панацея. Он работает только внутри своего контекста. Иногда решение — поднять z-index у родителя или создать новый контекст с помощью isolation: isolate.
Желаю успехов!







