Что такое z-index в CSS и как с его помощью управлять слоями на странице
С этим свойством вы сможете разместить один элемент поверх другого.
Представьте ситуацию: вы сверстали выпадающее меню, но при открытии оно прячется под соседним блоком — под шапкой сайта или баннером. Кажется, что элемент должен быть сверху, однако браузер рисует слои по своим правилам.
Чтобы управлять порядком наложения элементов при их пересечении, в CSS есть свойство z-index. И в этой статье мы разберём, что такое z-index, почему оно иногда не срабатывает и как его правильно применять в современных проектах.
Содержание
- Что такое z-index и зачем оно нужно
- Как работает наложение элементов
- Контекст наложения и z-index
- Типичные ошибки при работе с z-index
Что такое z-index и зачем оно нужно
Когда браузер отображает страницу, каждый элемент занимает определённое место в двухмерном пространстве: по горизонтали (ось X) и по вертикали (ось Y). Этих осей достаточно, чтобы описать обычный поток документа, где элементы располагаются сверху вниз в том порядке, в котором они указаны в HTML-коде.
Но когда вы видите всплывающее окно поверх основного контента, элементы начинают пересекаться в пространстве. Здесь появляется третья ось, Z, которая направлена перпендикулярно экрану. Элементы с большим значением по оси Z располагаются ближе к зрителю и визуально перекрывают те, что находятся глубже. Свойство z-index как раз и задаёт числовое значение положения элемента по этой оси, чтобы вы могли контролировать порядок наложения слоёв.
Числовое значение z-index — это всегда целое число, которое может быть положительным, отрицательным или нулём. Также у него есть значение auto, которое используется по умолчанию. Отрицательные значения отправляют элемент за обычный поток документа, положительные — выдвигают вперёд, а ноль оставляет на базовом уровне наложения. Значение auto означает, что браузер рассчитывает порядок наложения, исходя из структуры документа.
Чем больше число, тем выше элемент в стопке слоёв. При этом диапазон у z‑index практически не ограничен — вы можете использовать любые целые числа: хоть от −1 до 10, или от 100 до 10 000, или даже 999 999. Главное, чтобы выбранные значения оставались понятными в контексте вашего проекта.
Для наглядности попробуйте представить веб-страницу как колоду игральных карт, разложенных на столе: z-index определяет, какая карта лежит сверху и перекрывает остальные, а какая находится снизу и скрыта под другими картами.

С помощью z-index разработчики создают модальные окна, различные всплывающие подсказки, фиксированные шапки в меню, выпадающие списки, а также сложные анимации и прочие интерактивные компоненты, в которых элементы должны накладываться друг на друга в строго определённом порядке.
Понимание работы z-index помогает контролировать наложение элементов и быстро находить причину, почему нужный блок оказывается под другими.
Как работает наложение элементов
Когда элементы на странице пересекаются, браузер должен решить, какой из них рисовать сверху. На это влияет сразу несколько факторов: порядок элементов в HTML, позиционирование и другие CSS-свойства, которые формируют слои.
Если никакие правила наложения не заданы, браузер опирается на порядок в разметке: то есть элемент, который стоит позже в DOM-дереве, отображается поверх предыдущего. Это работает как принцип «последний — сверху».
Предположим, у вас есть два блока:
<div class="block-1">Первый блок</div>
<div class="block-2">Второй блок</div>Если они перекрываются из-за абсолютного позиционирования или отрицательных отступов, то верхним окажется .block-2, потому что он ниже.
А вот добавление свойства z-index позволяет вам явно управлять порядком наложения элементов. Но важно помнить, что оно работает только для позиционированных элементов — то есть тех, у которых свойство position имеет значение relative, absolute, fixed или sticky. Если у элемента position: static (значение по умолчанию), то z-index не будет иметь никакого эффекта.
Применим к нашим двум блокам позиционирование и z-index:
.block-1 {
position: relative;
z-index: 10;
}
.block-2 {
position: relative;
z-index: 5;
}Теперь благодаря большему значению z-index первый блок будет отображаться поверх .block-2, несмотря на то, что в HTML он по-прежнему идёт раньше.
Когда важно разместить один элемент на самом верху, новички часто допускают такую ошибку: они ставят z-index: 9999, но забывают про position — в результате браузер просто проигнорирует это значение, и элемент останется на прежнем уровне. Исключение здесь — прямые дочерние элементы flex- и grid-контейнеров: для них z-index работает даже без явного указания position.
Но даже при этом z-index иногда ведёт себя неожиданно. Причина в том, что оно не является глобальной шкалой для страницы, и его значения сравниваются только между элементами внутри одного контекста наложения. Что такое контекст наложения и почему он важен — разберём в следующем разделе.
Контекст наложения и z-index
Контекст наложения (stacking context) — это изолированная область внутри документа, где браузер формирует иерархию слоёв и сравнивает значения z‑index-элементов. Элементы внутри контекста конкурируют друг с другом по z‑index и выстраиваются в порядке наложения. Однако элементы из разных контекстов не сравниваются напрямую: браузер сначала определяет, какой контекст выше, а затем упорядочивает элементы внутри каждого контекста.
Представьте две стопки карт, которые находятся рядом и одна лежит выше другой. Внутри каждой стопки вы можете менять порядок карт как угодно — перекладывать их выше или ниже друг друга. Но при этом вся стопка целиком по-прежнему остаётся выше или ниже другой стопки. Поэтому даже карта с z-index: 999 из нижней стопки всё равно не окажется поверх карты с z-index: 1 из верхней стопки: браузер сначала смотрит на порядок самих стопок (то есть контекстов наложения), а уже потом на порядок карт внутри каждой из них.

Изображение: Skillbox Media
Новый контекст создаётся автоматически, когда элемент получает определённые CSS-свойства: позиционирование (position: relative, absolute, fixed или sticky) с явным z-index, прозрачность (opacity < 1), трансформации (transform, filter, perspective), свойство изоляции isolation: isolate, а также некоторые другие свойства вроде will-change или contain. Прямые дочерние элементы flex- и grid-контейнеров с явным z-index тоже формируют свой контекст. И ещё не забудем про тег <html> — он всегда создаёт контекст наложения по умолчанию.
Отдельного внимания заслуживают вложенные контексты, где часто возникают неожиданные ситуации. Дочерний элемент не может вырваться за пределы своего контекста, сколь бы большим ни было его значение z-index, — вы уже видели это на примере с картами. Теперь посмотрите на похожий пример в коде:
.parent {
position: relative;
z-index: 1;
}
.child {
position: absolute;
z-index: 999999;
}
.sibling {
position: relative;
z-index: 2;
}Порядок отображения будет такой: .parent с .child внутри — снизу, а .sibling — сверху. Блок .parent создаёт контекст с z-index: 1, и .child оказывается заперт: его z-index: 999999 имеет значение только внутри этого контекста. А вот .sibling создаёт отдельный контекст с z-index: 2. Браузер сравнивает именно их: 1 против 2 — и .sibling выигрывает. До значений внутри .parent дело даже не доходит.
Типичные ошибки при работе с z-index
Чаще всего z-index не работает из-за position: static. Чтобы свойство применилось, задайте position: relative, absolute, fixed или sticky.
/* Не работает */
.element {
z-index: 999;
}
/* Работает */
.element {
position: relative;
z-index: 999;
}Ещё одна частая проблема — конфликт контекстов. Если родительский элемент всплывающего окна создаёт свой контекст, дочернее окно с z-index: 9999 всё равно окажется под шапкой сайта — если контекст шапки выше контекста родителя попапа. Как мы уже разобрали, браузер сравнивает контексты родителей, а не сами элементы.
Чтобы это исправить, вы можете повысить z-index у .container (родителя попапа) — тогда весь контекст окажется поверх .header. Альтернативный вариант — вынести блок .popup за пределы .container в HTML. Тогда попап создаст уже собственный контекст наложения и будет сравниваться с .header напрямую.
.container {
position: relative;
z-index: 1; /* Родитель .popup — его контекст ниже шапки */
}
.popup {
position: absolute;
z-index: 9999; /* Высокий z-index бесполезен — .popup не выйдет за пределы .container */
}
.header {
position: relative;
z-index: 10; /* Контекст шапки выше контекста .container — значит, шапка перекрывает всё внутри него */
}Также некоторые CSS-свойства могут незаметно создавать новый контекст наложения, даже если вы этого не планировали. Чаще всего это opacity, любые transform и filter, а также will-change. Если z-index вдруг перестало работать после добавления одного из этих свойств — скорее всего, причина именно в них.
Если какое-то свойство мешает нужному порядку наложения, попробуйте его убрать или заменить. Но если не получается, вынесите проблемный элемент из вложенности — туда, где его контекст не будет конфликтовать с остальными.
.element {
opacity: 0.99; /* Создаёт контекст */
transform: translateZ(0); /* Тоже создаёт */
filter: blur(0); /* И это */
will-change: transform; /* И это */
}В любом случае, когда z-index ведёт себя неожиданно, стоит открыть Chrome DevTools и перейти в меню с тремя точками ⋮ → More tools → Layers. В этом разделе вы можете посмотреть страницу в 3D-режиме и понять, какие элементы создают композитные слои и как они расположены относительно друг друга.

Скриншот: Skillbox Media
Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!

