← Назад к вопросам

Почему не видна разница в z-index в нескольких div?

2.0 Middle🔥 61 комментариев
#HTML и CSS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему не видна разница в 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;
}

Полный список способов создания контекста наложения

  1. root элемент (<html>)
  2. position != static + z-index != auto
  3. opacity < 1
  4. transform != none
  5. filter != none
  6. mix-blend-mode != normal
  7. will-change: любое из вышеперечисленных
  8. contain: layout, paint, strict
  9. backdrop-filter != none
  10. perspective != none
  11. clip-path != none
  12. mask, mask-image, mask-border != none
  13. isolation: isolate
  14. -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; /* Локально внутри модала */
}

Ключевые выводы

  1. z-index работает только с position != static
  2. Новые контексты наложения создают opacity, transform, filter и другие свойства
  3. z-index локален внутри контекста наложения
  4. Родитель с контекстом никогда не будет ниже элемента вне контекста
  5. Используйте opacity: rgba вместо opacity свойства
  6. Используйте CSS переменные для организации z-index значений

Понимание контекстов наложения — это одна из самых важных концепций в CSS. Это решит 99% проблем с z-index.

Почему не видна разница в z-index в нескольких div? | PrepBro