Сайт о телевидении

Сайт о телевидении

» » Контексты наложения или когда z-index не работает. CSS слои, абсолютное и относительное позиционирование, z-index

Контексты наложения или когда z-index не работает. CSS слои, абсолютное и относительное позиционирование, z-index

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

«Ха!» - промелькнуло у меня в голове. Наверное, в одном из стилей не хватает свойства «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-оси и управляет z-index . Это свойство работает только для элементов, у которых значение position задано как absolute , fixed или relative .

    Краткая информация

    Обозначения

    Описание Пример
    <тип> Указывает тип значения. <размер>
    A && B Значения должны выводиться в указанном порядке. <размер> && <цвет>
    A | B Указывает, что надо выбрать только одно значение из предложенных (A или B). normal | small-caps
    A || B Каждое значение может использоваться самостоятельно или совместно с другими в произвольном порядке. width || count
    Группирует значения. [ crop || cross ]
    * Повторять ноль или больше раз. [,<время>]*
    + Повторять один или больше раз. <число>+
    ? Указанный тип, слово или группа не является обязательным. inset?
    {A, B} Повторять не менее A, но не более B раз. <радиус>{1,4}
    # Повторять один или больше раз через запятую. <время>#
    ×

    Значения

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

    Кроме числовых значений применяется auto — порядок элементов в этом случае строится автоматически, исходя из их положения в коде HTML и принадлежности к родителю, поскольку дочерние элементы имеют тот же номер, что их родительский элемент.

    Пример

    Порядок карт

    В данном примере при наведении курсора на карту она выходит на передний край, частично перекрывая остальные собой остальные изображения (рис. 1).

    Рис. 1. Изменение порядка карт

    Объектная модель

    Объект .style.zIndex

    Примечание

    Список, созданный с помощью