Почему элементы с z-index никогда не могут покрыть своего потомка
Сегодня, после 4 часов отладки, я усвоил это правило:
Родительский элемент никогда не сможет покрыть (сложить поверх) свой дочерний элемент, если у родительского элемента есть z-индекс любого значения, независимо от того, как вы изменили CSS дочернего элемента.
Мой вопрос: как я могу понять это поведение по логике? Это в спецификации? Это где-то в документе?
Код (также в Code Pen https://codepen.io/anon/pen/ywyrLq):
<div class="container">
<h1>1. I can never be covered by parent if my z-index is positive.</h1>
<h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>
.container {
width: 600px;
height: 600px;
background-color: salmon;
position: relative;
z-index: 99;
margin-top: 20px;
padding-top: 10px;
}
h1 {
background-color: pink;
position: relative;
z-index: -1;
font-family: monospace;
}
5 ответов
Есть две важные вещи, которые вы должны знать: порядок рисования и контекст укладки. Если вы обратитесь к спецификации, вы можете найти, как и когда элементы окрашены.
- Контексты стека, сформированные позиционированными потомками с отрицательными z-индексами (исключая 0) в порядке z-index (сначала наиболее отрицательный), затем в порядке дерева.
- Все позиционированные, непрозрачные или преобразованные потомки в древовидном порядке делятся на следующие категории:
- Все позиционированные потомки с 'z-index: auto' или 'z-index: 0', в древовидном порядке.
- Контексты суммирования, образованные позиционированными потомками с z-индексами, большими или равными 1, в порядке z-индекса (наименьший сначала), затем в порядке дерева.
Из этого ясно, что мы сначала красим элементы с отрицательным z-index
на этапе (3), затем тот, с z-index
равен 0 на шаге (8) и, наконец, те, с положительным z-index
на этапе (9), что логично. мы также можем прочитать:
Каждый блок принадлежит одному контексту стека. Каждый блок в данном контексте стека имеет целочисленный уровень стека, который является его положением на оси z относительно других блоков в том же контексте стека. Ящики с более высокими уровнями стека всегда форматируются перед ячейками с более низкими уровнями стека. Коробки могут иметь отрицательные уровни стека. Ящики с одинаковым уровнем стека в контексте стекирования располагаются снизу вверх в соответствии с порядком дерева документов.
Также
Элемент, который устанавливает локальный контекст стека, генерирует блок, который имеет два уровня стека: один для контекста стека, который он создает (всегда 0), и один для контекста стека, которому он принадлежит (заданный свойством z-index).
Чтобы понять, когда будет нарисован каждый элемент, вам нужно знать его контекст стека и уровень стека внутри этого контекста стека (определяется z-index
). Вам также необходимо знать, устанавливает ли этот элемент контекст стека или нет. Это сложная часть, потому что установка z-index
сделаем это:
Для позиционированного блока свойство z-index указывает:
- Уровень стека блока в текущем контексте стека.
- Устанавливает ли бокс контекст для стека
а также
Это целое число - уровень стека сгенерированного блока в текущем контексте стека. Поле также устанавливает новый контекст стека.
Теперь у нас есть вся информация, чтобы лучше понять каждый случай. Если родительский элемент имеет z-index
указано отличается от auto
тогда это создаст контекст стека, таким образом, дочерний элемент будет нарисован внутри независимо от того, z-index
последнего (отрицательный или положительный). z-index
дочернего элемента просто скажет нам порядок paiting внутри родительского элемента. (это охватывает ваш второй пункт)
Теперь, если только дочерний элемент имеет положительный z-index
и мы ничего не устанавливаем для родительского элемента, тогда с учетом порядка рисования дочерний элемент будет окрашен позже (на шаге (9)) и родительский на шаге (8). Единственный логичный способ нарисовать родительский элемент - увеличить z-index
но при этом мы попадем в предыдущий случай, когда родительский объект устанавливает контекст стека, а дочерний элемент будет принадлежать ему.
Невозможно иметь родительский элемент над дочерним элементом при установке положительного z-index
ребенку. Также нет никакого способа, чтобы родитель был выше ребенка, если мы установим z-index
на родительский элемент, отличный от auto
(положительный или отрицательный).
Единственный случай, когда у нас может быть ребенок ниже его родителя, это установить отрицательный z-index
к дочернему элементу и оставить родителя с z-index
auto, таким образом, этот не будет создавать контекст стека и, следуя порядку рисования, ребенок будет нарисован первым.
В дополнение к z-index
есть другие свойства, которые создают контекст стека. В случае, если вы столкнулись с ожидаемым порядком размещения, вам нужно рассмотреть эти свойства, чтобы увидеть, создан ли контекст размещения.
Хороший способ думать об этом состоит в том, что у каждого родителя есть свой собственный стековый контекст. Родственные элементы имеют общий порядок размещения родительских элементов и, следовательно, могут перекрывать друг друга.
Дочерний элемент ВСЕГДА получает контекст стека на основе своего родителя. Отсюда необходимость отрицательного значения z-index, чтобы вытолкнуть дочерний элемент "позади" его стекового контекста parent (0).
Единственный способ удалить элемент из контекста его родителя - использовать position: fixed
так как это по сути заставляет его использовать окно для контекста.
Документация Mozilla действительно говорит
CSS-свойство z-index устанавливает z-порядок позиционируемого элемента и его потомков или элементов flex.
Вот некоторая дополнительная логика из другой статьи Stackru, касающейся детей против потомков.
Как я могу понять это поведение по логике?
Мне трудно понять вашу проблему по логике. Родитель содержит своих детей. Чаша может быть накрыта другой чашей. Но вы не можете накрыть суп миской, если не выложите суп из миски.
z-Index устанавливает порядок перекрывающихся элементов. Родитель не может перекрывать своего ребенка.
ImhO, это совершенно логично.
На этот вопрос уже есть хороший ответ, но я хотел бы добавить еще одну вещь: если вы нашли этот вопрос, есть большая вероятность, что ваша проблема должна быть решена с помощью overflow , а не z-index.