Размещение относительно оси z

Продолжая разговор о позиционировании, неизбежно возникнут ситуации, когда два элемента попытаются сосуществовать на одном месте с визуальной точки зрения. Очевидно, одному из них придется перекрывать другой, но как управлять тем, какой элемент окажется сверху? Вот где в игру вступает свойство z-index. Свойство z-index позволяет менять способ перекрытия элементов друг другом. Свое имя оно получило от системы координат, в которой горизонталь – это ось x, а вертикаль – ось y. В этом случае третья ось, которая проходит по нормали к поверхности отображения, обозначается как ось z. Таким образом, элементам присваиваются значения координат по этой оси, и представлены эти значения с помощью свойства z-index. В этой системе координат элемент, значение z-index которого больше, располагается ближе к читателю, чем те, значение z-index которых меньше. Этот процесс называется занесением в стек (stacking).

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

p#first {position: absolute; top: 0; left: 0;
width: 20%; height: 10em; z-index: 8;}
p#second {position: absolute; top: 0; left: 10%;
width: 30%; height: 5em; z-index: 4;}
p#third {position: absolute; top: 15%; left: 5%;
width: 15%; height: 10em; z-index: 1;}
p#fourth {position: absolute; top: 10%; left: 15%;
width: 40%; height: 10em; z-index: 0;}

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


Если абзацы располагаются в соответствии с их номерами, то логичным был бы порядок от меньшего к большему: p#first (первый), p#second (второй), p#third (третий), p#fourth (четвертый). При этом p#first был бы помещен позади остальных трех элементов, а p#fourth – впереди. Как показывает предыдущий пример, вовсе не обязательно, чтобы значения z-index были последовательными. Можно задать любое целое любой величины. Чтобы гарантированно оставить элемент поверх всего остального, можно применить, например, такое правило: z-index: 100000. В большинстве случаев это обеспечивает ожидаемое поведение, но если объявить z-index другого элемента равным 100001 (или выше), то этот другой окажется впереди.

Элемент, свойству z-index которого присвоено значение (отличное от auto), создает собственный локальный контекст занесения в стек (stacking context). Следовательно, все потомки элемента имеют собственный порядок занесения в стек относительно элемента-предка. Очень похожим образом элементы формируют новые блоки-контейнеры:

p {border: 1px solid; background: #DDD; margin: 0;}
b {background: #808080;}
em {background: #BBB;}
#one {position: absolute; top: 0; left: 0; width: 50%; height: 10em;
z-index: 10;}
#two {position: absolute; top: 5em; left: 25%; width: 50%; height: 10em;
z-index: 7;}
#three {position: absolute; top: 11em; left: 0; width: 50%; height: 10em;
z-index: 1;}
#one b {position: absolute; right: -5em; top: 4em; width: 20em;
z-index: -404;}
#two b {position: absolute; right: -3em; top: auto;
z-index: 36;}
#two em {position: absolute; bottom: -0.75em; left: 7em; right: -2em;
z-index: -42;}
#three b {position: absolute; left: 3em; top: 3.5em; width: 25em;
z-index: 23;}

Заметьте, куда в порядке занесения в стек попадают элементы b и em.


Каждый из них позиционирован правильно, относительно своего родительского элемента, конечно. Однако внимательно рассмотрите потомков элемента p#two. Элемент b расположен поверх своего родителя, em – сзади, и оба они расположились поверх p#three! Причина в том, что значения 36 и –42 свойства z-index рассматриваются относительно p#two, а не документа в целом. В некотором смысле p#two и все его дочерние элементы имеют одинаковый z -index, равный 7, но при этом у каждого из них есть еще и собственный мини-z-index в рамках контекста p#two. Иначе говоря, это как будто z-index элемента b равен 7,36, а значение для em – 7,–42. Все это просто предполагаемые абстрактные значения; они никак не связаны со спецификацией. Однако такая система помогает проиллюстрировать, как устанавливается общий порядок занесения в стек. Рассмотрим:

p#one 10
p#one b 10,-404
p#two b 7,36
p#two 7
p#two em 7,-42
p#three b 1,23
p#three 1

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


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

p#one 10,0
p#one b 10,-404
p#two b 7,36
p#two 7,0
p#two em 7,-42
p#three b 1,23
p#three 1,0

Осталось рассмотреть еще одно значение. Вот что говорит спецификация о применяемом по умолчанию значении auto: Уровень занесения в стек генерируемого блока в текущем контексте занесения в стек аналогичен уровню его родительского блока. Блок не образует нового локального контекста занесения в стек. (CSS2.1: 9.9.1) Таким образом, любой элемент со значением z-index: auto может быть интерпретирован, как если ему задано значение z-index: 0. Теперь, однако, вас, наверное, интересует, что происходит с элементами, имеющими отрицательное значение z-index и являющимися частью контекста занесения в стек начального блока-контейнера. Например, спросите себя, что должно произойти в результате применения следующей разметки:


Where am I?




Учитывая правила занесения в стек, элемент body должен находиться в том же контексте занесения в стек, что и блок его родителя, поэтому он принимается за 0. Он не образует новый контекст занесения в стек, поэтому абсолютно позиционированный элемент p размещается в том же контексте занесения в стек, что и элемент body (т. е. в начальном блоке-контейнере). Иначе говоря, абзац размещается позади элемента body. Если body имеет непрозрачный фон, абзац исчезнет. Таким, во всяком случае, был возможный результат в CSS2. В CSS2.1 правила занесения в стек изменились, поэтому элемент не может оказаться под фоном его контекста занесения в стек. Другими словами, рассматривается случай, когда элемент body образует блок-контейнер для своих потомков (если бы он был относительно позиционированным, например). Абсолютно позиционированный элемент, происходящий от элемента body, не может быть помещен под фоном body, хотя может располагаться под его содержимым.

На момент написания данной книги Mozilla и родственные броузеры полностью скрывают абзац, даже если и для элемента body, и для элемента html задан прозрачный фон. Это ошибка. Другие агенты пользователя, такие как Internet Explorer, размещают абзац поверх фона body, даже если он у него есть. Согласно CSS2.1 это поведение правильное. Вывод таков, что отрицательные значения z-index могут привести к непредсказуемым результатам, поэтому задавать их надо осторожно.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела CSS на эту тему:
Блок-контейнер
Блоки-контейнеры и абсолютно позиционированные элементы
Видимость элементов
Задание ширины и высоты
Запрет на обтекание