Очередной блог фрилансера. Как работает z-index

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

В нормальном потоке position: static элементы располагаются последовательно один за другим в том порядке, в котором они определены в html-документе. По умолчанию установлен z-index: auto; .


Рис. 1. Позиционирование элементов вдоль оси Z

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


Рис. 2. Воздействие свойства z-index на позиционированные элементы

Контекст наложения

Если для элементов свойства z-index и position не заданы явно, контекст наложения равен порядку их расположения в исходном коде. Если для элементов не задан z-index , браузер отображает элементы на странице в следующем порядке:

Корневой элемент

Позиционированные position элементы в порядке их следования в исходном коде. Последний из них будет расположен на переднем плане.




Рис. 3. Порядок расположения элементов в 3D пространстве по умолчанию

Lorem ipsum dolor sit amet, consectetur adipiscing elit...

Как видно из рисунка, элемент с position: absolute; находится на переднем плане, далее идет текст, под ним располагаются плавающие элементы с float: left; , не позиционированные блочные элементы расположены на заднем плане (так как плавающие и позиционированные элементы удаляются из потока, то блочные не позиционированные элементы их игнорируют и располагаются друг за другом, в соответствии с разметкой, поэтому элемент

расположился под элементом
) .

Свойство z-index создает новый контекст наложения. Оно позволяет изменить порядок наложения позиционированных элементов . Элементы будут отображаться на странице в следующем порядке (если для них не заданы свойства, влияющие на контекст наложения — opacity , filter , transform):

Корневой элемент , который содержит все элементы веб-странице.

Позиционированные элементы с отрицательным значением z-index .

Блочные элементы, не плавающие и не позиционированные.

Плавающие float не позиционированные элементы в порядке их расположения в исходном коде.

Строковые не позиционированные элементы (текст, изображения).

Позиционированные элементы со значениями z-index: 0; и z-index: auto; .

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


Рис. 4. Свойство z-index создает новый контекст наложения элементов в 3D пространстве

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

«Ха!» - промелькнуло у меня в голове. Наверное, в одном из стилей не хватает свойства «z-index», позволяющее управлять порядком наложения позиционированных элементов на странице. Начал добавлять «z-index» и ничего хорошего из этого не вышло. Какое бы значение я ему не присваивал, элементы из центральной части страницы все равно перекрывали мою менюшку.

Неоднозначный z-index

Казалось бы, что может быть сложного с z-index? Всем известно, что позиционированные элементы на странице могут накладываться друг на друга. Управлять порядком наложения как раз и позволяет свойство «z-index». Например, если у нас два элемента с присвоенным значением z-index – 5 и 10, то последний будет выведен на переднем плане, т.к. десять больше пяти, а больше, значит ближе. Когда свойство «z-index» не задано, то порядок наложения определяется порядком элементов в документе.

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

У контекста наложения есть корневой элемент. Например, у нас есть какой-то

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

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

Когда формируется новый контекст наложения

Спецификация определяет несколько условий формирования контекста наложения:

  • В роли элемента выступает корневой элемент HTML-документа (тэг);
  • Элементу задана прозрачность (вспоминаем про свойство opacity) меньше единицы;
  • Элемент позиционирован не статически и свойство z-index != auto.
  • Забегая вперед, скажу, для решения моей задачи потребовалось лишь добавить прозрачность (opacity ) для корневого элемента меню и все сразу заработало, как было задумано.

    Как отображаются элементы в одном контексте наложения

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

  • Корневой элемент контекста, т.е. элемент, образовавший контекст наложения;
  • Позиционированные элементы (+ потомки) с отрицательным z-index. Элементы, у которых z-index больше, отображаются ближе. Элементы с одинаковым значением «z-index» располагаются по порядку (в соответствии с разметкой);
  • Не позиционированные элементы располагаются по порядку;
  • Позиционированные элементы (+ потомки) со значением z-index в auto располагаются по порядку (в соответствии с разметкой);
  • Позиционированные элементы (+ потомки) с положительным значением z-index (чем больше z-index, тем ближе будет элемент). Если у двух элементов одинаковый «z-index», то порядок отображения определяется разметкой.
  • Проблема z-index в том, что многие просто не понимают, как он работает.
    Всё, описанное ниже, есть в спецификации W3C. К сожалению, не все её читают.

    Описание проблемы:

    Итак, пусть у нас есть HTML код, состоящий из 3 элементов.
    Каждый из них внутри себя содержит по одному. А каждый, в свою очередь, имеет свой фон: красный, зеленый и синий, соответственно. Плюс ко всему, каждый позиционирован абсолютно левого верхнего края документа таким образом, что он немного перекрывает собой следующий за ним. Первый имеет z-index , равный 1, у остальных двух z-index не задан.

    Ниже представлен HTML код с базовым css оформлением.

    Red
    Green
    Blue

    .red, .green, .blue { position: absolute; } .red { background: red; z-index: 1; } .green { background: green; } .blue { background: blue; }
    Пример на jsfiddle

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

    • Нельзя менять HTML разметку
    • Нельзя менять/добавлять z-index к элементам
    • Нельзя менять/добавлять позиционирование к элементам

    Решение:

    Решение состоит в том, чтобы добавить прозрачность чуть меньше единицы первому (родителю красного).
    Вот css, иллюстрирующий это:
    div:first-child { opacity: .99; }

    Хм, что-то тут не так. Причем тут вообще прозрачность? Каким образом она может влиять на порядок перекрытия элементов? Вы думаете так же? Добро пожаловать в клуб!
    Надеюсь, во второй части статьи всё встанет на свои места.

    Порядок наложения элементов:

    Z-index кажется очень простым: чем значение больше, тем ближе к нам будет элемент, т.е. элемент с z-index 5 будет перекрывать собой элемент с z-index 2, верно? На самом деле нет.
    Это и есть проблема z-index. Всё кажется настолько очевидным, что большинство разработчиков не уделяют достаточно времени для изучения этого вопроса.

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

    Если свойства z-index и позиционирование не заданы явно, всё просто: порядок наложения равен порядку следования элементов в HTML. (На самом деле всё немного сложнее , но пока вы не будете использовать отрицательные значения отступов для перекрытия строчных элементов, вы не будете сталкиваться с крайними случаями)

    Если вы явно указываете позиционирование элементам (и их детям), то такие элементы будут перекрывать собой элементы без явно заданного свойства позиционирования. (Говоря «явно указываете позиционирование» – я имею ввиду любое значение, кроме статического, например: абсолютное, или относительное).

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

    Контекст наложения

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

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

    Новый контекст может быть сформирован в следующих случаях:

    • Если элемент – корневой элемент документа (элемент)
      Если элемент позиционирован не статически и его значение z-index не равно auto
      Если элемент имеет прозрачность менее 1

    Розовый квадрат имеет значение z-index, отличное от auto, что создает новый контекст наложения. Появление контекста наложения влияет на то, как отображаются дочерние элементы.

    Можно изменить порядок наложения дочерних элементов розового квадрата. Однако их z-индекс имеет смысл только в контексте наложения . Это означает, что мы не сможем расположить оранжевый квадрат перед синим, потому что они находятся в разных контекстах наложения.

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






    https://codepen.io/ivhed/pen/erGoJE

    Контекст наложения формируется не только при применении свойства z-index. Существует несколько других свойств , которые заставляют элементы создавать контексты наложения. Некоторые примеры: filter (фильтр), opacity (непрозрачность), and transform (трансформация).

    Вернемся к нашему предыдущему примеру. Синий квадрат снова связан с розовым. На этот раз вместо добавления свойства z-index розовому квадрату мы применим к нему фильтр .





    Blue, .pink, .orange {
    position: absolute;
    } .pink {
    filter: hue-rotate(20deg);
    } .blue {
    z-index: 2;
    } .orange {
    z-index: 3;
    } .green {
    z-index: 100;
    }

    https://codepen.io/ivhed/pen/LmWMQb

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

    Резюме

    Используя z-индекс для позиционируемых элементов, мы можем изменить порядок наложения элементов, заданный по умолчанию.

    При применении определенных CSS-свойств элемент может формировать контекст наложения. Значения z-индекса имеют смысл только в одинаковом контексте наложения.

    Для получения дополнительной информации о принципе работы свойства z-index, рекомендую вам ознакомиться с этой статьей . Именно она вдохновляла меня в процессе работы над этой публикацией.

    Проблема z-index в том, что многие просто не понимают, как он работает.
    Всё, описанное ниже, есть в спецификации W3C. К сожалению, не все её читают.

    Описание проблемы:

    Итак, пусть у нас есть HTML код, состоящий из 3 элементов.
    Каждый из них внутри себя содержит по одному. А каждый, в свою очередь, имеет свой фон: красный, зеленый и синий, соответственно. Плюс ко всему, каждый позиционирован абсолютно левого верхнего края документа таким образом, что он немного перекрывает собой следующий за ним. Первый имеет z-index , равный 1, у остальных двух z-index не задан.

    Ниже представлен HTML код с базовым css оформлением.

    Red
    Green
    Blue

    .red, .green, .blue { position: absolute; } .red { background: red; z-index: 1; } .green { background: green; } .blue { background: blue; }
    Пример на jsfiddle

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

    • Нельзя менять HTML разметку
    • Нельзя менять/добавлять z-index к элементам
    • Нельзя менять/добавлять позиционирование к элементам

    Решение:

    Решение состоит в том, чтобы добавить прозрачность чуть меньше единицы первому (родителю красного).
    Вот css, иллюстрирующий это:
    div:first-child { opacity: .99; }

    Хм, что-то тут не так. Причем тут вообще прозрачность? Каким образом она может влиять на порядок перекрытия элементов? Вы думаете так же? Добро пожаловать в клуб!
    Надеюсь, во второй части статьи всё встанет на свои места.

    Порядок наложения элементов:

    Z-index кажется очень простым: чем значение больше, тем ближе к нам будет элемент, т.е. элемент с z-index 5 будет перекрывать собой элемент с z-index 2, верно? На самом деле нет.
    Это и есть проблема z-index. Всё кажется настолько очевидным, что большинство разработчиков не уделяют достаточно времени для изучения этого вопроса.

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

    Если свойства z-index и позиционирование не заданы явно, всё просто: порядок наложения равен порядку следования элементов в HTML. (На самом деле всё немного сложнее , но пока вы не будете использовать отрицательные значения отступов для перекрытия строчных элементов, вы не будете сталкиваться с крайними случаями)

    Если вы явно указываете позиционирование элементам (и их детям), то такие элементы будут перекрывать собой элементы без явно заданного свойства позиционирования. (Говоря «явно указываете позиционирование» – я имею ввиду любое значение, кроме статического, например: абсолютное, или относительное).

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

    Контекст наложения

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

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

    Новый контекст может быть сформирован в следующих случаях:

    • Если элемент – корневой элемент документа (элемент)
      Если элемент позиционирован не статически и его значение z-index не равно auto
      Если элемент имеет прозрачность менее 1


    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: