CSS свойство z-index.

Опубликовано: 18 февраля 2014      Автор:

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

В статье рассматриваются вопросы, связанные с пониманием свойства z-index, а также детали его применения на практике. Данное свойство, как собственно и немало других CSS свойств, обладает рядом различий в обработке отдельными браузерами. Особенно это касается ранних версий Internet Explorer и Firefox.

Свойство z-index предназначено для определения уровня «глубины» отображения позиционированного элемента страницы. Под глубиной в данном случае подразумевается расположение форматируемого элемента относительно третьей оси координат Z, которая, как известно, перпендикулярна плоскости, образуемой более привычными для нас осями X и Y. Свойство z-index может принимать три значения: числовое, auto и inherit.

  • числовое значение — целые положительные или отрицательные числа и ноль. Чем больше число, тем ближе к поверхности находится объект, перекрывая собой соседние элементы. Если у двух, перекрывающих друг друга элементов это свойство имеет одинаковые значения, то выше располагается тот, который описан в HTML коде ниже.
  • auto — элементы располагаются в порядке, предусмотренном исходным кодом документа. При этом учитываются родственные связи элементов, так как дочерние элементы наследуют уровень глубины родительских элементов.
  • inherit — наследование значения одноименного свойства родительского элемента.

Таким образом, помимо возможности смещения объекта страницы в одну из сторон на плоскости (вертикальное и горизонтальное направления), в результате применения данного свойства, получаем возможность переместить элемент на задний либо передний план (фронтальное направление) относительно других, расположенных «внахлест» элементов. В итоге можно говорить о формировании так называемого визуального стека элементов, который формируется вследствие установки различных значений свойства z-index. При этом, чем меньше значение свойства, тем глубже в стеке находится элемент.

Принцип отображения элементов в зависимости от значения их свойства z-index

Принцип размещения элементов в зависимости от значения их свойства z-index.

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

  • Элемент участвует в схеме абсолютного позиционирования (position: absolute или position: fixed).
  • Элемент задействован в относительной схеме позиционирования (position: relative).
  • Либо элемент является плавающим (определено свойство float со значением отличным от none).

То есть это и есть условия, о которых шла речь в начале данной статьи, необходимые для того, чтобы увидеть эффект от применения свойства z-index.

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

  1. Фон и границы того элемента, в контексте которого и формируется стек. Этот элемент образует так называемый стековый контекст. Согласно CSS 2.1 спецификации, такими являются позиционированные элементы, с вычисляемым значением свойства z-index, отличным от auto. То есть если для позиционированного элемента не установлено свойство z-index или если оно установлено явно со значением auto (что делать бессмысленно), то этот элемент не образует новый стековый контекст. Во всех остальных случаях, когда для позиционированного элемента свойство z-index задано со значением отличным от auto, то он образует новый стековый контекст.
    Следующий уровень спецификации — CSS3, допускает образование стекового контекста, путем определения и других свойств элемента, к примеру, opacity.
  2. Потомки контекстного элемента, образующие новые стековые контексты (условия, которым должны отвечать такие элементы, указаны в предыдущем пункте), имеющие отрицательные значения свойства z-index.
  3. Не позиционированные поточные потомки контекстного элемента, которые не относятся к элементам строчного уровня.
  4. Элементы с установленным свойством float и их содержимое.
  5. Не позиционированные строчные потомки контекстного элемента.
  6. Образующие новые стековые контексты дочерние элементы контекстного контейнера (условия, которым должны удовлетворять такие элементы, указаны в первом пункте) и его позиционированные потомки, значение свойства z-index которых равно нулю.
  7. Потомки родительского контекстного элемента, образующие дочерние стековые контексты (удовлетворяющие условиям из первого пункта), имеющие положительные значения свойства z-index.

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

Итак, давайте с помощью представленной ниже диаграммы разберем подробнее определенный спецификацией порядок отрисовки слоев документа.

Порядок размщения слоев документа.

Порядок отображения слоев документа.

слой А
В этом, самом нижнем слое отображения находится элемент, образующий стековый контекст. На диаграмме это корневой элемент body. Корневым элементом документа образуется корневой стековый контекст, который, собственно, ни чем не отличается от других стековых контекстов за исключением того обстоятельства, что он не имеет родительских стековых контекстов. Слой А не обязательно содержит корневой стековый контекст, это может быть любой другой стековый контекст документа, в котором задействованы все остальные, представленные на диаграмме контексты и элементы.
слой В
Как и определено выше, в этом слое отображается потомок контекстного, в нашем случае body элемента, образующий новый стековый контекст — элемент div-1 с отрицательным значением свойства z-index. Стоить отметить один важный, но не всегда очевидный момент: потомком элемента А может быть любой элемент В исходного документа, который является либо его дочерним элементом, либо дочерним элементом его потомка (определение взято из спецификации). В нашем случае это позиционированный див с установкой z-index: -2. Обратите внимание, что используемые в диаграмме позиционированные элементы участвуют в разных схемах позиционирования, что в данном конкретном случае не имеет никакого значения. То есть для них, вместо значения absolute или relative можно свободно использовать значение fixed и наоборот.
слой С
Здесь представлен обычный поточный блочный элемент div-2. К нему не применяются никакие CSS свойства.
слой D
Следующий слой представляет плавающие элементы и их содержимое. На диаграмме это смещенный влево элемент div-3. Для него, естественно, должно быть установлено свойство float со значением отличным от none, в нашем случае это left.
слой E
Этот слой отображения используется для представления строчных потомков контекстного элемента (включая внутристрочные блоки и внутристрочные таблицы), к которым не применяется позиционирование. На диаграмме в роли такого элемента выступает строчный элемент span. В обычных условиях строчные элементы, которые обтекают смещенные боксы (у нас это div-3), никогда не накладываются на них, а размещаются рядом с ними со стороны, противоположной смещению плавающего элемента. Но для того, чтобы продемонстрировать то, что этот слой располагается «выше» предыдущего слоя D, для span элемента применено левое поле с отрицательным значением (margin-left: -140px). Таким образом мы добились наложения двух элементов, не используя при этом позиционирование.
слой F
Этот слой я решил немного усложнить. В первую очередь он как и полагается содержит образующий новый стековый контекст потомок div-4 с нулевым значением свойства z-index, перекрывающий собой все элементы, размещенные в предыдущих слоях от А до Е включительно. Далее в рамках этого элемента изображены дочерние элементы параграфы (p-1 и p-2), которые в свою очередь образуют новые стековые контексты, являющиеся дочерними по отношению к стековому контексту, образованному элементом div-4. Дочерние элементы параграфы накладываются друг на друга, поскольку они позиционированы, это показано с помощью двух подслоев f1-b и f2-g. Подслой f1-b выполняет ту же функцию, что и внешний слой B (представляет элемент div-1), но в рамках стекового контекста, установленного элементом div-4. А подслой f2-g, в свою очередь аналогичен внешнему слою G (представляет элемент div-5), который рассматривается в следующем пункте. Здесь следует сделать очень важное замечание. В нашем случае, когда элементу div-4 явно задано свойство z-index со значением 0, он образует новый стековый контекст. Если же этого не сделать, и не применить к этому элементу свойство z-index явно или применить его со значением auto, то в этом случае вычисляемое значение данного свойства для этого элемента будет равно auto, а это означает, что он не может устанавливать новый стековый контекст. Немного странная ситуация, поскольку как гласит спецификация, если явно указать для свойства z-index значение auto, то стековый уровень этого элемента будет равен нулю и он не образует новый стековый контекст, а если для этого элемента явно указать значение 0, то его стековый уровень по-прежнему будет равен нулю, но при этом он образует новый стековый контекст.
слой G
Здесь мы имеем дело с последним, самым «верхним» слоем, в котором отображаются все потомки контекстного элемента, образующие новые стековые контексты, значения свойства z-index которых положительны. Представителем таких потомков является элемент div-5. Я не просто так показал в предыдущем слое F два подслоя. Обратите внимание на то, что хотя значения свойства z-index элементов, представленных в этих подслоях (p-1 и p-2) превышает либо ниже соответствующих значений у внешних элементов, они не взаимодействуют с ними. У первого параграфа p-1, к примеру, стековый уровень равен -3, но он располагается выше элемента div-2 хотя его стековый уровень выше (-2). А у второго p-2 параграфа стековый уровень выше, чем у элемента div-5, тем не менее, он находится под ним. Это объясняется тем, что элементы параграфы представляют подуровни или дочерние стековые контексты элемента div-4, а согласно CSS 2.1 спецификации «с точки зрения своего родительского стекового контекста, любой стековый контекст является неделимым, то есть боксы, задействованные в других стековых контекстах, не могут отображаться между боксами текущего стекового контекста». Или другими словами, боксы разных стековых контекстов не могут накладываться друг на друга, то есть взаимодействовать визуально.

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

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

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

Любой бокс документа принадлежит одному из стековых контекстов. При этом в рамках любого подобного контекста такие элементы как:

  • позиционированные элементы с нулевым стековым уровнем, не образующие новый стековый контекст (т.е. вычисляемое значение свойства z-index которых равно auto) — слой F;
  • не позиционированные плавающие блоки — слой D;
  • внутристрочные блоки и внутристрочные таблицы — слой E;

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

Одной из самых распространенных ошибок, связанных с применением данного свойства на практике у начинающих верстальщиков может быть заблуждение относительно того, что это свойство можно назначать не позиционированным элементам. То есть, те элементы, у которых явно или не явно (по умолчанию) установлено свойство position : static, никак не отреагируют на установку каких-либо значений свойству z-index. Это свойство дает эффект применительно только к позиционированным элементам, то есть к тем, у которых свойство position принимает одно из трех значений: absolute, relative или fixed.

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

IE 6

Если на странице присутствует элемент <select>, то обычная последовательность отображения элементов нарушается, потому, что <select> является особым приоритетным элементом управления – windows-контролом. При этом не зависимо от того, какие значения CSS свойств z-index и position установлены для других элементов, <select> отображается выше всех.

IE 6 и 7

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

Firefox 2

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