Skip to content

То, о чем Вам никто не расскажет о z-index

Проблема с использованием z-index заключается в том, что очень немногие люди понимают, как это действительно работает. Это не сложно, но если вы не нашли время прочитать его спецификацию, то почти наверняка все важные аспекты для Вас останутся в полном неведении.

Проблема

В нижеприведенном HTML коде есть три элемента <div>, и каждом из них содержится один элемент <span>. Им дается цвет фона — красный, зеленый и синий соответственно. Каждый <span> расположен в левом верхнем углу документа, слегка перекрывая другие элементы
<span> . Первый <span> имеет z-Index равный 1, а два других не имеют этого свойства.

<div>
<span class="red">Red</span>
</div>
<div>
<span class="green">Green</span>
</div>
<div>
<span class="blue">Blue</span>
</div>
.red, .green, .blue {
position: absolute;
}
.red {
background: red;
z-index: 1;
}
.green {
background: green;
}
.blue {
background: blue;
}
z-index1

Вот задача: попытаться переместить красный <span> под синий и зеленый <span> , но нельзя пробовать следующие решения:

  1. Не изменяйть HTML разметку в любом случае.
  2. Не добавлять / изменять свойство z-index любого элемента.
  3. Не добавлять / изменять свойство position любого элемента.

Вот как это должно выглядеть

z-index2

Решение

Решение состоит в том, чтобы добавить значение непрозрачности меньше чем 1 к первому div (родитель красного span). Вот CSS:

div:first-child {
opacity: .99;
}

Если вы сейчас в шоке и чешете затылок, то я Вас понимаю. Я тоже был шокирован подобным образом, когда я впервые наткнулся на этот вопрос.

Порядок укладки

Свойство z-index кажется таким простым: элементы с более высоким z-index находятся выше элементов с более низким z-index, верно? Ну а на самом деле нет. Это является частью проблемы использования z-index. Данное свойство кажется настолько простым, поэтому большинство разработчиков не отводят времени, чтобы ознакомиться с правилами.

Каждый элемент в документе HTML может быть cпереди или позади других элементов. Правила определения этого порядка довольно четко определены в спецификации, но, как я уже говорил, не все разработчики в полной мере понимают их.

Когда свойства z-index и position не указаны, в основном, порядок наложения такой же, как порядок появления в HTML. Это на самом деле немного сложнее, но пока вы не используете отрицательны значения для margin строковых элементов, вы, вероятно, не будете сталкиваться с крайними случаями.

Когда вы добавляете position, любой позиционированный элемент (и его потомки) отображаются перед любыми не позиционированными элементами.

Примечание: здесь и далее говоря, что элемент «позиционирован» означает, что он имеет значение position relative, absolute и т.д., но не static.

Наконец, когда z-index есть у нескольких элементов, все становится немного сложнее. Сначала это естественно предположить, элементы с более высоким значением z-index находятся выше элементов с более меньшим z-index, и любой элемент, которому прописано свойство z-index, находится выше любого элемента без z-index, но это не так все просто. Прежде всего, z-index действует только на позиционированные элементы. Если вы пытаетесь установить z-index элементу без свойства position (не static), то это Вам ничего не даст. Во-вторых, z-index может создать перекрытие блоков, и теперь то, что казалось простым стало работать намного сложнее.

Перекрытие блоков

Группы элементов с общим родителем, двигаться вперед или назад вместе в порядке наложения составляют то, что известно как перекрытие блоков. Полное понимание перекрытия блоков является ключом к использованию z-index в работе.

Каждый перекрывающий блок имеет один элемент HTML в качестве корневого элемента. Если мы создадим элемент в перекрывающем блоке, то он будет выше любого другого блока даже с огромным z-index в миллиард!

Новое перекрытие блоков может быть сформировано одним из трех способов:

  1. Если элемент является корневым элементом документа (тег html)
  2. Когда элемент позиционируется и значение z-index отлично от auto
  3. Когда элемент имеет значение непрозрачности менее 1

Первый и второй пути формирования перекрытия блоков имеет много смысла и, как правило, понимается веб-разработчиками.

Третий способ с использованием непрозрачности почти никогда не упоминался за пределами документы спецификации W3C.

Определение позиции элемента в стеке

На самом деле глобальное определение порядка размещения всех элементов на странице крайне сложное и далеко выходит за рамки данной статьи. Но для большинства намерений и целей достаточно базового понимание этого. Итак, давайте начнем с нарушения порядка на отдельные перекрытия блоков.

Порядок укладки в перекрытии блоков

Вот основные правила для определения порядка размещения в одном перекрытии блоков (от задней стенки к передней):

  1. Корневой элемент перекрывания блоков
  2. Позиционированные элементы (и их потомки) с отрицательным значением z-index (чем выше значение, тем выше показан; элементы с одинаковым значением сортируются в соответствии с появлением в HTML)
  3. Не позиционированные элементы (отсортированы по времени появления в HTML)
  4. Позиционированные элементы (и их потомки) с z-index:auto (отсортированы по времени появления в HTML)
  5. Позиционированные элементы (и их потомки) с положительным значением z-index (чем выше значение, тем выше показан; элементы с одинаковым значением сортируются в соответствии с появлением в HTML)
z-index3

Примечание: позиционируемые элементы с отрицательным значением z-index появляются позади всех остальных элементов.

Глобальный порядок укладки

Если вы устанавливаете z-index в миллиард к элементу, и он не появляется выше в порядке наложения, посмотрите на его предков в DOM-дереве и проверьте, образует ли любой из его родителей перекрытие блоков. Если нет, то z-index не принесет Вам никакой пользы.

Последний шаг

Возвращаясь к исходной задаче, я воссоздал структуру HTML добавив комментарии внутрь каждого тега указывает его место в порядке наложения, используя исходный CSS.

<div><!-- 1 -->
<span class="red"><!-- 6 --></span>
</div>
<div><!-- 2 -->
<span class="green"><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span class="blue"><!-- 5 --></span>
</div>

Когда мы добавляем прозрачность к первому div, укладка изменения порядка такая:

<div><!-- 1 -->
<span class="red"><!-- 1.1 --></span>
</div>
<div><!-- 2 -->
<span class="green"><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span class="blue"><!-- 5 --></span>
</div>

span.red раньше был 6-ым, но он повысился до 1.1.

Надеюсь, что Вам стало чуть более понятно, почему красный прямоугольник переместился за другие прямоугольники. Когда мы добавили прозрачность родителю span.red мы сформировали 1/3 перекрытия блоков, и, из этого следует, что значение z-index на span.red применяются только в новом перекрытии. Потому что первый <div> (к которому мы применили непрозрачность) и его «братья» не позиционированы и не имеют значение z-index, их порядок размещения определяется их порядком в HTML, а это означает, что первый <div>, и все элементы, содержащиеся в перекрытии, оказываются за вторым и третьим элементами <div>.

Источник: Philip Watson