Разработчик
0,0
рейтинг
21 января 2013 в 13:30

Разработка → То, что вам никто не говорил о z-index перевод


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

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


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

Ниже представлен HTML код с базовым css оформлением.
<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;
}

Пример на jsfiddle

Задача: сделать так, чтобы красный
 был позади синего и зеленого, при этом не нарушая ни одно из следующих правил:
  • Нельзя менять HTML разметку
  • Нельзя менять/добавлять z-index к элементам
  • Нельзя менять/добавлять позиционирование к элементам


Решение:


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


Пример на jsfiddle

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

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


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
Вы знаете, что css свойство opacity влияет на наложение элементов?

Проголосовало 2733 человека. Воздержалось 327 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Перевод: Philip Walton
Алексей @alverspb
карма
25,2
рейтинг 0,0
Разработчик
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (29)

  • +40
    IE9 голосует за третий пункт…
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        В этом и есть суть офиц. тестов. Надо пройти только то, что просит тест. Остальное допилим, пусть пока полетает.
        • НЛО прилетело и опубликовало эту надпись здесь
  • +11
    Спасибо, про прозрачость не знал. Слава джизосу, подобных ограничений никогда не встречал.
    Ну и кажется, количество букв в статье можно легко уменьшить в 2 раза. И хорошо бы отметить особенности поведения z-index'а в ИЕ.
    • 0
      Собственно, сам не знал и не сталкивался до последнего времени)
      Про IE допишу, как свободное время будет.
  • +9
    IEшникам по барабану этот баг в головах разработчиков спецификаций и тут я с его разработчиками полностью солидарен
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      То есть, стандарт говорит еще и о создании нового контекста в результате применения css трансформаций или это по странному стечению обстоятельств — особенность реализации большинства браузеров?

      По ссылке из статьи, ведущей на описание zIndex на сайте W3C собственно и о влиянии opacity ничего нет. Нужно смотреть где-то в другом месте?
      • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Спасибо за статью, это для меня открытие.
    Возможно стоило бы как-то детальнее рассказать о таких сущностях, как контексты, с ними все еще не полностью понятно.

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

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

    а. Возможно ли это сделать не меняя html-разметку?
    б. Если это невозможно, поможет ли разрешение создавать элемент, промежуточный в иерархии между родителем и детьми?

    Буду очень признателен, если найдется время прояснить ситуацию
    • 0
      Насколько я сам в этом всем разобрался, в общем случае не получится так сделать.
      Вы рано или поздно наткнетесь на ситуацию, при которой элемент в одном контексте будет перекрываться другим, в не зависимости от установленных значений z-index.
      Но танцевать всё равно надо от конкретной реализуемой задачи и структуры DOM-а!
      б. Если это невозможно, поможет ли разрешение создавать элемент, промежуточный в иерархии между родителем и детьми?

      В некоторых случаях да, т.к. при добавлении элемента (при условии, что мы установим ему позиционирование и z-index) он образует новый контекст, тем самым его дочерние элементы унаследуют этот контекст, и элементы всплывут, как в примере в статье.
  • +1
    хм… Блоку текста присваиваем z-index:-1, поверх него div с максимальной прозрачностью. Вуаля! Получаем защиту текста от выделения и копирования. Простенькую, конечно, но даже ее 40-60% типовых «пользователей интернета» не обойдет. Зато никаких JS.
    • +1
      Для блока с текстом можно ::selection {background: transparent} поставить, правда работает нивезде.
      • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Извините, я может не заметил, но не могли бы вы уточнить как это в разных браузерах работает (если по спецификации, то все хорошо, а если нет...)? К сожалению у самого сейчас нет возможности проверить. За статью спасибо.
    • НЛО прилетело и опубликовало эту надпись здесь
      • +1
        Всё верно, пока тоже ничего другого не нашел.
        Кстати, IE9/10 не только с absolute, но и с fixed аналогично не работает.
  • 0
    Хочу просто заметить на всякий случай, что знать это конечно хороше, но в жизни такие хаки лучше не применять если совсем не прижмет.
    • НЛО прилетело и опубликовало эту надпись здесь
  • +1
    Ещё один геморрой от w3c.
    Ну зачем это было сделано, зачем?!
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    этот хак уже не пашет?

    оба примера одинаковые (хотя… тот что с прозрачностью — в начале загрузки всё таки на секунду отодвигается назад — но потом обратно вперед)
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Google Chrome самая последняя, v30

        Opera v12 пашет нормально
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            да вы правы — открыл в инкогнито — и всё нормализовалось
  • 0
    Про прозрачность надо знать и помнить ибо сафари (точно не скажу с какой версии но точно в 6.2) очень трепетно относится к расположению таких элементов и может получится что элементы попап будет перекрыт безвредным на первый взгляд элементом.

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