Когда элементы выходят из потока и начинают перекрывать друг друга, возникает вопрос: кто окажется сверху? Выпадающее меню должно лечь поверх контента, модальное окно — поверх всего, а подсказка — над кнопкой. Порядком слоёв по глубине управляет свойство z-index. Но иногда оно ведёт себя неожиданно: элемент с огромным z-index всё равно оказывается под другим. Причина — контекст наложения, и понимание этого механизма избавит вас от одной из самых загадочных проблем вёрстки.
После этого урока вы сможете управлять тем, какие элементы лежат выше, а какие ниже, и понимать, почему z-index иногда «не работает», — а значит, уверенно строить меню, модальные окна и подсказки.
Что уже умеем / что добавим
Вы умеете выводить элементы из потока через absolute, fixed и sticky — то есть создавать перекрытия. Теперь научимся управлять порядком этих перекрытий. В сквозном проекте мы наведём порядок в слоях: прилипающая шапка ляжет поверх контента, а бейдж и всплывающие элементы получат правильную глубину.
Что вы узнаете в рамках статьи
- Как браузер по умолчанию решает, что лежит сверху.
- Как свойство
z-indexуправляет порядком слоёв. - Почему
z-indexработает только у позиционированных элементов. - Что такое контекст наложения и почему
z-indexиногда «не срабатывает».
Ключевые термины
z-index— числовой порядок элемента по глубине (по оси Z).- Ось Z — воображаемая ось «к пользователю»: чем больше
z-index, тем ближе слой. - Позиционированный элемент — элемент с
positionнеstatic. - Контекст наложения — независимая группа слоёв, внутри которой сравниваются
z-index.
Порядок слоёв по умолчанию
Когда элементы перекрываются, браузер по умолчанию рисует их в порядке появления в коде: то, что идёт ниже в HTML, ложится поверх того, что выше. Позиционированные элементы (с position не static) при этом рисуются над обычными элементами потока.
То есть без всякого z-index уже действует логика: более поздний в коде и позиционированный элемент оказывается сверху. Часто этого достаточно. Но когда нужно явно управлять глубиной — например, поднять элемент над тем, что идёт после него, — в дело вступает z-index.
Свойство z-index
z-index задаёт числовой порядок элемента по глубине. Чем больше число, тем ближе к пользователю (выше) находится элемент:
.dropdown {
position: absolute;
z-index: 10;
}
.content {
position: relative;
z-index: 1;
}
Здесь .dropdown с z-index: 10 ляжет поверх .content с z-index: 1, независимо от их порядка в коде. Значения можно задавать любые целые — важно лишь их соотношение: больше — выше. Отрицательные значения (z-index: -1) уводят элемент под другие. На практике удобно оставлять между слоями запас (10, 20, 100), чтобы потом было куда вставить промежуточный слой.
z-index работает не всегда
Важнейшая деталь: z-index действует только на позиционированных элементах — тех, у кого position равен relative, absolute, fixed или sticky. У обычного элемента в потоке (position: static) свойство z-index просто игнорируется.
/* z-index не сработает: position по умолчанию static */
.box {
z-index: 100;
}
/* А так сработает */
.box {
position: relative;
z-index: 100;
}
Это частая причина недоумения: элементу задали большой z-index, а он не поднимается. Первое, что нужно проверить, — задано ли ему position. Без позиционирования z-index бессилен. Запомните это правило — оно экономит массу времени при отладке.
Контекст наложения
Второй источник загадок — контекст наложения. Это независимая группа слоёв: z-index элементов сравниваются только внутри одного контекста, а не по всей странице. Новый контекст создаёт, например, позиционированный элемент с собственным z-index (а также некоторые современные свойства вроде opacity меньше 1 или transform).
Смысл в том, что дочерний элемент не может «выпрыгнуть» выше соседей своего родителя, даже с гигантским z-index. Если родитель находится ниже другого блока, все его дети — тоже ниже, каким бы большим ни был их z-index.
.card {
position: relative;
z-index: 1;
}
.card__badge {
position: absolute;
z-index: 999;
}
Здесь бейдж с z-index: 999 поднимется над содержимым своей карточки, но не над элементами, лежащими выше самой карточки в её контексте. Если модальное окно упорно оказывается под чем-то, несмотря на большой z-index, почти всегда виноват контекст наложения родителя. Решение — поднимать не сам элемент, а его контекст (родителя) или размещать модальные окна ближе к концу body.
Применяем в проекте
Наведём порядок в слоях сайта. Прилипающая шапка должна лежать поверх прокручиваемого контента, а бейдж — над содержимым карточки. Зададим им осмысленные z-index.
.site-header {
position: sticky;
top: 0;
z-index: 100;
background-color: #fff;
}
.card {
position: relative;
}
.card__badge {
position: absolute;
top: 12px;
right: 12px;
z-index: 2;
}
Обновите страницу и прокрутите её: прилипшая шапка уверенно ложится поверх любого контента, который под неё заезжает, а бейдж «Хит» остаётся над содержимым карточки. Мы задали шапке заметно больший z-index, чем внутренним элементам, — так она гарантированно наверху. Заметьте, что z-index мы задали только позиционированным элементам: без position он бы не сработал.
Частые ошибки
z-indexбезposition.
Уstaticэлемента свойство игнорируется; сначала задайтеrelative,absolute,fixedилиsticky.- Борьба с контекстом наложения.
Огромныйz-indexне поднимет элемент выше чужого контекста; поднимайте родителя или меняйте структуру. - Гонка значений.
Ставитьz-index: 99999вслепую — плохая привычка; задавайте осмысленную шкалу слоёв с запасом. - Забыть про фон у верхнего слоя.
Слой сверху без фона пропускает то, что под ним; для шапок и модальных окон задавайте фон.
Итоги
Поздравляем — вы завершили раздел о позиционировании и разобрались с самой коварной его частью! Теперь вы понимаете, как браузер укладывает слои по умолчанию, умеете управлять глубиной через z-index, помните, что он работает только у позиционированных элементов, и знаете про контекст наложения — причину большинства «необъяснимых» перекрытий. Слои вашего сайта выстроены осознанно: шапка сверху, бейджи на местах, ничего не налезает друг на друга случайно.
Отличная работа! Впереди — заключительный раздел курса, самый практичный: адаптивная вёрстка. Мы научимся делать сайт, который безупречно выглядит и на телефоне, и на десктопе, начиная с мета-тега viewport и подхода mobile-first.