Почему не видна разница в z-index в нескольких div?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Почему не видна разница в z-index в нескольких div?
Это одна из самых распространённых проблем при работе с CSS. Разработчики устанавливают разные значения z-index, но элементы не располагаются так, как ожидается. Причина в том, что z-index работает только в определённых контекстах.
Основное правило: z-index работает только в контексте наложения
z-index действует только на элементы с позиционированием (position: relative, absolute, fixed, sticky). На элементы с position: static (по умолчанию) z-index вообще не влияет.
/* Неправильно — z-index не сработает */
.div1 {
z-index: 100;
/* position: static (по умолчанию) */
}
.div2 {
z-index: 1;
/* position: static (по умолчанию) */
}
/* Правильно — z-index сработает */
.div1 {
position: relative;
z-index: 100;
}
.div2 {
position: relative;
z-index: 1;
}
Контексты наложения (Stacking Context)
Это критическое понятие. Контекст наложения — это трёхмерное пространство, в котором элементы расположены по оси Z. Новый контекст создаётся несколькими способами:
1. position + z-index
.parent {
position: relative;
z-index: 1; /* Создаёт новый контекст наложения */
}
.child {
position: relative;
z-index: 9999; /* Но это значение локально для parent! */
}
2. opacity < 1
.element {
opacity: 0.99; /* Создаёт новый контекст! */
z-index: 100;
}
3. transform, filter, perspective
.element {
transform: translateZ(0); /* Создаёт новый контекст */
z-index: 100;
}
.element2 {
filter: blur(5px); /* Тоже создаёт новый контекст */
z-index: 100;
}
4. mix-blend-mode
.element {
mix-blend-mode: multiply; /* Создаёт новый контекст */
}
5. will-change
.element {
will-change: transform; /* Может создать новый контекст */
}
Проблема 1: Вложенные контексты
Самая частая причина. Если родитель имеет position и z-index, он создаёт новый контекст наложения. Элементы внутри этого контекста не могут быть выше элементов вне контекста, даже если у них больший z-index.
.container1 {
position: relative;
z-index: 1; /* Создаёт контекст наложения */
}
.container1 .element {
position: relative;
z-index: 9999; /* Будет ниже container2, т.к. container1 имеет z-index: 1 */
}
.container2 {
position: relative;
z-index: 2; /* Выше container1 */
}
.container2 .element {
position: relative;
z-index: 1; /* Даже с меньшим значением, будет выше container1 */
}
Проблема 2: opacity создаёт контекст
Это один из самых коварных случаев. Разработчик добавляет opacity для прозрачности, не зная, что это создаёт новый контекст наложения.
.modal {
opacity: 0.9; /* Создаёт контекст наложения! */
z-index: 9999;
}
.overlay {
opacity: 1;
z-index: 10000; /* Может не помочь */
}
/* Исправление */
.modal {
background-color: rgba(0, 0, 0, 0.9); /* Прозрачность без контекста */
z-index: 9999;
}
Проблема 3: transform и filter
Модернизация CSS добавила много свойств, создающих контексты наложения. Это было сделано для оптимизации, но часто застаёт разработчиков врасплох.
.card {
transform: scale(1); /* Создаёт контекст наложения! */
}
.element {
z-index: 9999;
position: relative; /* Не поможет быть выше .card */
}
/* Исправление */
.card {
/* Не используй transform только для позиционирования */
/* Используй вместо transform: translate() translate() */
position: relative;
}
Проблема 4: Забыли position
<div class="container">
<div class="box1" style="z-index: 100;">Box 1</div>
<div class="box2" style="z-index: 1;">Box 2</div>
</div>
/* Неправильно */
.box1, .box2 {
/* position: static по умолчанию */
/* z-index не работает */
}
/* Правильно */
.box1 {
position: relative;
z-index: 100;
}
.box2 {
position: relative;
z-index: 1;
}
Полный список способов создания контекста наложения
- root элемент (
<html>) - position != static + z-index != auto
- opacity < 1
- transform != none
- filter != none
- mix-blend-mode != normal
- will-change: любое из вышеперечисленных
- contain: layout, paint, strict
- backdrop-filter != none
- perspective != none
- clip-path != none
- mask, mask-image, mask-border != none
- isolation: isolate
- -webkit-mask != none (для старых браузеров)
Практический пример: Всплывающее окно
/* Родитель modal создаёт контекст */
.modal-wrapper {
position: fixed;
opacity: 0.95; /* ОШибка! Создаёт контекст */
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: absolute;
z-index: 9999; /* Не поможет, т.к. внутри контекста */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* Правильно */
.modal-wrapper {
position: fixed;
background: rgba(0, 0, 0, 0.5); /* Вместо opacity */
z-index: 999;
/* ... остальные стили */
}
.modal-content {
position: absolute;
z-index: 1; /* Теперь нормальное значение */
/* ... остальные стили */
}
Как отладить z-index проблемы
1. DevTools inspector
Откройте DevTools, нажмите на элемент, и смотрите его CSS свойства:
- Есть ли у элемента position: static?
- Есть ли opacity < 1?
- Есть ли transform?
- Есть ли filter?
2. Проверьте родителей
Пролистайте DOM дерево вверх. Может быть, родитель имеет нежелательный контекст наложения.
// Консоль JavaScript для проверки
const element = document.querySelector('.my-element');
const computed = window.getComputedStyle(element);
console.log({
position: computed.position,
zIndex: computed.zIndex,
opacity: computed.opacity,
transform: computed.transform,
filter: computed.filter
});
3. MDN Stacking Context
Отличная статья на MDN объясняет все детали: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioned_Layout/Understanding_z-index
Рекомендации по использованию z-index
/* Хорошая практика: используйте переменные */
:root {
--z-hidden: -1;
--z-normal: 1;
--z-dropdown: 100;
--z-sticky: 200;
--z-fixed: 300;
--z-modal: 1000;
--z-tooltip: 1100;
}
.modal {
position: fixed;
z-index: var(--z-modal);
}
.modal .close-button {
position: relative;
z-index: 1; /* Локально внутри модала */
}
Ключевые выводы
- z-index работает только с position != static
- Новые контексты наложения создают opacity, transform, filter и другие свойства
- z-index локален внутри контекста наложения
- Родитель с контекстом никогда не будет ниже элемента вне контекста
- Используйте opacity: rgba вместо opacity свойства
- Используйте CSS переменные для организации z-index значений
Понимание контекстов наложения — это одна из самых важных концепций в CSS. Это решит 99% проблем с z-index.