Глубокое понимание свойства CSS z-index

внешний интерфейс JavaScript CSS товар
Глубокое понимание свойства CSS z-index

исходный адрес

предисловие

Недавно я столкнулся с проблемой укладки DOM при использовании анимации CSS3, поэтому заново изучил z-index. Я чувствую, что это свойство CSS довольно сложное. Надеюсь, эта статья поможет вам заново понять прелесть z-index.

Вот как все пошло (предыстория немного длинная), и я недавно написал следующую страницу со списком:

Затем добавьте анимацию CSS3 к каждому элементу продукта, которая выглядит следующим образом:ДЕМО-адрес

Эффект после реализации, вероятно, будет таким (скриншот немного размыт, для просмотра рекомендуется кликнуть по адресу демо):


В Chrome это выглядит нормально, но когда я открываю его из Safari, я обнаруживаю, что анимация очень застряла:

При переключении между разными товарными позициями я обнаружу, что анимация страницы явно застряла.Думая об этом, для меня это не сложно, поэтому я добавляю аппаратное ускорение 3D-анимации к каждому товарному товару.Метод также очень прост, следующим образом :

.item {
  transform: translateZ(0);      /* 或者 will-change: transform; */
}

Это распространенный метод оптимизации для аппаратного ускорения.Если вы не понимаете, вы можете прочитать это:Включите аппаратное ускорение с помощью CSS, чтобы повысить производительность сайта.

После открытия Safari я обнаружил, что анимация страницы была очень плавной, а оптимизация аппаратного ускорения прошла успешно, но затем появилась новая проблема — проблема каскадирования элементов DOM, упомянутая в этой статье.

Хотя эффект анимации фиксирован, возникает проблема с укладкой элементов DOM на странице: то есть следующий элемент продукта будет охватывать всплывающее поле ввода в правом нижнем углу предмета продукта выше, а также нормальный Эффект Мы надеемся, что должно быть так:

Столкнулся с такой проблемой, первая реакция: значит буду увеличивать z-индекс коробки пули.Покрытие, сначала озадачился.

Наконец, я научился разбираться, прочитав некоторые материалы, и, наконец, нашел решение.Без лишних слов, я начну разбирать все знания, связанные с z-index, и, наконец, представлю решение вышеуказанной проблемы. (Следующее объяснение будет сопровождаться множеством вариантов использования, я вставлю весь код в jsfiddle для удобства, читатели могут щелкнуть демонстрационный адрес, чтобы просмотреть пример)

основы z-индекса

Во-первых, давайте введем z-index. Атрибут z-index используется для настройки порядка элементов и подэлементов на оси Z. Когда элемент перезаписывается, какой элемент находится сверху, а какой снизу. Как правило, элементы с более высокими значениями z-index переопределяют более низкие элементы.

Значение z-index по умолчанию — auto, которое может быть установлено как положительное или отрицательное целое число.Если не учитывать CSS3, будет работать только z-index элемента позиционирования (position:relative/absolute/fixed), если ваш z -index работает с непозиционированным элементом (также работает некоторый CSS3) и не имеет никакого эффекта. Например:демонстрационный адрес

Когда вы устанавливаете позиционирование для DOM-элемента, в силу вступает z-index элемента, по умолчанию стоит auto, вы можете просто сделать его эквивалентным z-index:0, например:демонстрационный адрес,Другими словами, предварительным условием для того, чтобы z-index вступил в силу, является то, что атрибут позиционирования (или некоторые атрибуты CSS3) должен быть установлен до того, как он начнет действовать.

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

уровень укладки

Элемент DOM, независимо от контекста наложения, определяет порядок отображения элементов по оси Z в соответствии с уровнем наложения.С точки зрения непрофессионала, когда различные элементы DOM комбинируются и перекрываются, их порядок отображения будет соответствовать правилам каскадных уровней, а z-индекс используется для настройки порядка отображения элемента, чтобы элемент мог перемещаться вверх и вниз.

Так как же выглядит каскадный уровень? Вот знаменитый уровень стека 7

Видно, что уровень каскадирования регулирует правила отрисовки при перекрытии элементов, с помощью этого правила несложно объяснить, почему красный квадрат в предыдущем примере перекрывает синий квадрат.Потому что при установке свойства position:relative элемент z-index:auto вступает в силу и поднимается уровень стека, который выше, чем у обычного встроенного элемента, поэтому выше будет отображаться красный квадрат.

Зная правила каскадирования уровней, я приведу несколько примеров для иллюстрации:

элементы inline/inline-block выше, чем элементы с плавающей запятой

Во-первых, элементы inline/inline-block выше, чем элементы с плавающей запятой:демонстрационный адрес

Хорошо видно, что текст (строчный элемент) закрывает изображение (плавающий элемент).

элементы inline/inline-block выше блочных элементов

демонстрационный адрес

Красный квадрат (встроенный блок) закрывает зеленый квадрат (блок), но поскольку текст (отображение: блок) принадлежит встроенному уровню, он находится на том же уровне, что и красный квадрат (встроенный блок), следуя принципу появится позже (поясняется позже), Не покрывается встроенными блочными элементами.

Элементы располагаются на одном уровне

Затем, когда два элемента уложены на одном уровне, необходимо соблюдать следующие два правила:

  1. более поздний принцип
  2. Тот, у кого самый большой z-индекс, находится на вершине

Последний принцип:

Критерий отставания означает, что когда элементы располагаются на одном уровне, DOM сзади перезапишет DOM спереди. Это легко понять, но это требует слишком много объяснений. Вот почему мы часто видим, почему более поздние элементы перезаписывают более ранние.

Как и в приведенном ранее примере, поскольку текст (display:block) относится к встроенному уровню и находится на том же уровне, что и красный квадрат (inline-block), он следует принципу последующего появления (поясняется позже) и не покрывается элементом inline-block, здесь я не буду публиковать еще один пример для иллюстрации.

Тот, у кого самый большой z-индекс, находится сверху:

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

Зная уровень стека, в основном до тех пор, пока определяется порядок отображения элементов в одном и том же контексте стека, но если он находится в другом контексте стека, как он отображается? Что означает этот контекст стека? Не волнуйся, просто посмотри вниз.

контекст стека

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

После введения концепции контекста стека давайте посмотрим, как создать контекст стека.

Обычно создается три больших типа контекстов стека:

  1. Создать контекст стека по умолчанию
  2. Необходимо инициировать создание контекста стека с помощью z-index.
  3. Нет необходимости инициировать создание контекста стека с помощью z-index.

1. Создайте контекст стека по умолчанию

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

2. Он должен запускаться z-index для создания контекста стека.

При создании контекста стека в зависимости от значения z-index:

  1. Значение позиции относительное/абсолютное/фиксированное (некоторые браузеры)
  2. Элемент Flex (родительский DISPLAY является flex | inline-flex), обратите внимание на дочерние элементы, а не на слой создания родительского элемента ниже

В этих двух случаях необходимо установить конкретное значение z-index, а для z-index нельзя установить значение auto, что является небольшой разницей между z-index: auto и z-index: 0.

Как мы упоминали ранее, при установке position: relative значение z-index auto вступит в силу, но в это время контекст стека не создается.Когда z-index не установлено на auto, даже если z-index: 0, элемент будет активирован. Создайте контекст стека.

3. Нет необходимости инициировать создание контекста стека с помощью z-index.

В этом случае это в основном запускается новыми свойствами в CSS3, общие из них:

  • Прозрачность непрозрачности элемента меньше 1
  • Значение режима смешивания элемента не является нормальным.
  • Следующие атрибуты элемента имеют значения, отличные от none:
    • transform
    • filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • Значение атрибута изоляции элемента isolate
  • Атрибут -webkit-overflow-scrolling элемента сенсорный
  • Свойство will-change элемента имеет значение, которое создаст контекст стека.

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

Сравните порядок отображения двух элементов DOM

Далее подведем итог, как сравнить порядок отображения двух элементов DOM?

  1. Если он находится в одном контексте стека, элементы отображаются в соответствии с правилами уровня стека.
  2. Если он находится в разных контекстах стека, сначала найдите контекст стека общего предка, а затем сравните уровень стека локального контекста стека, где два элемента расположены в общем контексте стека.

Тысячи слов сжаты в эти два предложения, но есть много моментов, на которые следует обратить внимание. Давайте сначала рассмотрим первый пункт:

общий контекст стека

Если он находится в одном контексте стека, элементы отображаются в соответствии с правилами уровня стека. Это было введено, когда был введен уровень стека. Стоит отметить, что элементы отношения родитель-потомок, скорее всего, будут в том же контексте стека.В этом случае иерархическое сравнение нижних элементов также отображается в соответствии с правилами каскадного уровня.

Например:демонстрационный адрес

Сравнение элемента .box и его дочернего элемента img: Поскольку img и .box принадлежат к одному и тому же контексту стека, поскольку z-индекс img равен -1, он опускается ниже родительского элемента, родительский элемент закрывает изображение, а img по-прежнему выше цвета фона тела, поскольку он соответствует 7-уровневому уровню наложения, нижняя часть должна быть фоном или границей контекста наложения (элемента тела).

Но если мы позволим элементу .box создайте локальный контекст укладки, он отличается. IM-ящик и элемент IMG также в одном контексте штабелирования, но контекст переключается на локальный контекст штабелирования.

демонстрационный адрес

Вы обнаружите, что: элемент img покрывает цвет фона .box, потому что цвет фона контекста стека всегда самый низкий, а контекст стека меняется с элемента body на элемент .box, но если это элемент span и элемент img под .box Для сравнения, встроенные элементы выше, чем элементы с отрицательным z-индексом, поэтому над изображением отображается 2222.

Цель этого примера — проиллюстрировать, что наложение родительских и дочерних элементов более вероятно, если родительский элемент является локальным контекстом наложения, а может и не быть локальным контекстом наложения, поэтому необходимо найти общий контекст наложения.

различные контексты стекирования

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

Обычное дерево DOM на странице выглядит так:Здесь Root, ParentX, ChildX — все элементы контекста стека, не обязательно родительские элементы ABCD.

  1. Элемент A хочет сравниться с элементом B или ChildB.Я очень доволен.Они принадлежат к одному и тому же контексту стека (ChildB), и его можно судить по уровню стека.
  2. Если элемент A хочет сравнить с C или ChildA, то найдите их общий контекст стека предка (ParentB) и после его нахождения сравните уровень стека в соответствии с локальным контекстом стека, где расположены два элемента в контексте стека предка ( вот ChildA и ChildB) для сравнения)
  3. Точно так же, если A хочет конкурировать с D, перейдите к контексту стекирования предков (Root), а затем сравните уровни стекирования ParentA и ParentB.

Это очень просто?Давайте проиллюстрируем это двумя простыми небольшими примерами:

Пример первый:демонстрационный адрес

Хотя z-index ребенка А: 9999 очень велик, при сравнении его с родительским B или дочерним B он не подходит для сравнения и может позволить только своему боссу parentA сравнивать, а parentA сравнивает с parentB, только чтобы выяснить: О, мой бог, получается, что ваш z-индекс 2 больше, чем мой, неуважительно, поэтому ребенок А и родитель А должны послушно оставаться под родителем Б.

Если мы немного изменим пример, чтобы parentA не создавал новый элемент контекста стека:демонстрационный адрес

Когда parentA больше не создает контекст стека, если childA хочет сравнить с childB, он больше не ограничивается parentA, а напрямую сравнивается с parentB (поскольку childA и parentB находятся в одном и том же контексте стека), очевидно, что childA находится наверху, что также Вот почему childA переопределяет parentB.

Решение проблемы

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

Поскольку к каждому элементу продукта добавляется transform: translateZ(0), контекст стека создается для каждого элемента продукта.Согласно вышеупомянутым правилам, элементы DOM в каждом элементе продукта не зависят друг от друга, в зависимости от каждого элемента продукта ( каждый локальный контекст укладки), и поскольку уровень укладки этих элементов продукта одинаков (такой же, как z-index: auto), следует принципу «последним пришел — первым», в результате чего последний элемент покрывает первый элемент. Возьмем простой пример:демонстрационный адрес

Точно так же, даже если вы добавите большой атрибут z-index к дочернему элементу, он не изменит его уровень стека. Единственный способ — изменить значение z-index элемента. является только всплывающей частью. , а часть всплывающего окна не отображается по умолчанию. Она будет отображаться только при наведении мыши на вход. Самый простой способ - увеличить значение z-index при наведении мыши на вход. предмет, чтобы уничтожить его.демонстрационный адрес

Окончательный упрощенный эффект:

Лучшие практики

Говоря об этом, можно сделать вывод.В процессе обучения я смотрел видео, записанное ранее Чжан Синьсюй.Он предложил несколько лучших практик.Я думаю, что это неплохо.Вот краткое введение:

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

Для неплавающих элементов слоя не используйте слишком большой z-индекс для настройки порядка отображения и гибко используйте каскадный уровень и принцип захода сзади, чтобы элемент отображался правильно. Adjust. Для неплавающих элементов не рекомендуется иметь значение z-index больше 2. Для элементов DOM достаточно -1, 0, 1, 2, чтобы элементы отображались в правильном порядке.

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

конец

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

Ссылка на ссылку