Почти два года назад вышла статья «What no one told you about z-index» (и её перевод на Хабре «То, что вам никто не говорил о z-index»), авторы которой рассказывают о малоизвестной (76% проголосовавших пользователей Хабра слышат об этом впервые), но документированной возможности создания нового контекста наложения указав opacity
меньше единицы.
Но несмотря на название статьи, авторы не рассказали вам ещё кое о чём.
Элементы с общими родителями, перемещающиеся на передний или задний план вместе известны как контекст наложения. Понимание контекста наложения является ключом к пониманию
z-index
и порядка наложения элементов.Каждый контекст наложения имеет свой корневой элемент в HTML структуре. В момент формирования нового контекста на элементе, все дочерние элементы так же попадают в этот контекст и занимают своё место в порядке наложения. Если элемент располагается в самом низу одного контекста наложения, то никаким мыслимым и немыслимым образом не получится отобразить его над другим элементом в соседнем контексте наложения, располагающимся выше по иерархии, даже с установленным
z-index
равным миллиону.
— Из статьи «То, что вам никто не говорил о z-index». Для понимания темы настоятельно рекомендую к ознакомлению либо её, либо классический труд на MDN.
Новый контекст наложения формируется в случаях:
- Корневой элемент (
<html>
) всегда содержит корневой контекст наложения. Любой элемент на странице, не участвующий в локальном контексте наложения (сформированном любым из последующих вариантов), участвует в корневом контексте наложения. - Элемент с
position
отличным отstatic
и значениемz-index
отличным отauto
. Кроме одного исключения дляposition: fixed
, но я это вынес в отдельный пункт. - Элемент имеет значение
opacity
меньше, чем1
. - Flex-элемент со значением
z-index
отличным отauto
, даже в случаеposition: static
. - Трансформированные элементы: значение
transform
отличное отnone
;transform-style
со значениемpreserve-3d
; иperspective
со значением отличным отnone
. - CSS Regions: установление значения
flow-from
отличное отnone
для элемента сcontent
отличным отnormal
. - Paged Media: каждый Page-Margin Box устанавливает собственный контекст наложения.
- И наконец пункт, ради которого я и пишу эту статью — мобильные браузеры на основе WebKit, а также Google Chrome 22+ всегда создают новый контекст наложения для
position: fixed
-элементов, даже сz-index: auto
!
Рассмотрим последний сценарий более подробно. Он единственный из всего списка не описан стандартами W3C.
На этой странице две похожие DOM-структуры:
<div class="container">
<div class="green"></div>
<div class="pink"></div>
<div class="fixed">
<div class="orange"></div>
</div>
</div>
Со стилями:
.container { position:absolute; }
.green { position:relative; z-index: 1; }
.pink { position:relative: z-index: 3; }
.fixed { position:fixed; }
.orange { position:relative; z-index: 2; }
Единственное отличие — во втором варианте добавлен opacity: .99
для .fixed
. Поскольку в Google Chrome (начиная с 22 версии), а также в мобильных WebKit-браузерах фиксировано-позиционированные элементы создают новый контекст наложения (так же как и элементы с opacity: .99
) — в этих браузерах обе фигуры будут идентичны.
В свою очередь остальные браузеры покажут иную картину.
Так получилось потому, что значение z-index
нашего .fixed
-элемента равно auto
(что не создаёт контекста наложения в левой фигуре). .orange
оказался в контексте наложения .container
и встал согласно своему z-index
(после .green
, но перед .pink
).
Зачем Google Chrome пошёл против стандартов?
К слову, первыми так стали делать Apple в Safari на iOS 5+, а также основные браузеры для Android (кроме Firefox).
Чтобы понять зачем, стоило покопаться в архиве www-style@w3.org и найти письмо Джеймса Робинсона из Google, в котором он подробно излагает суть проблемы, приводит пример (который я использовал в статье) и рассказывает, что новый контекст наложения для position: fixed
-элементов в мобильных браузерах создаётся для оптимизации скролла и улучшения user experience (хотя я так и не могу понять, о какой конкретно оптимизации идёт речь и буду признателен если кто-нибудь сможет мне объяснить).
As a result, in MobileSafari on iOS 5+ and the most recent Android browser position:fixed elements establish a new stacking context. As a result, the two test cases in webstuff.nfshost.com/tests/fixpos.html render identically to each other. Firefox on Android appears to render the same way as desktop Firefox, and scrolling is quite janky. Chrome on Android Beta does something more complicated on this page that results in a desktop-like rendering, but I consider that a bug (hey, it's Beta) and intend to bring its behavior in line with MobileSafari. I do not have access to any Windows Phone devices, but I'm curious what its browser does.
Таким образом в Google Chrome просто сделали одинаковое поведение фиксированных элементов на desktop и mobile, проигнорировав рекомендации W3C. Хотя с их стороны были предложения принять такое поведение position: fixed
в стандарт, но консорциум пока не проявил интереса к этим изменениям.
Как обстоят дела на текущий момент?
Подводя итоги, новый контекст наложения для position: fixed
формируется в следующих браузерах:
- Мобильные браузеры на основе WebKit
- Google Chrome 22+ (и его производные)
- Apple Safari 6.1+ (Desktop)
- Opera Blink (а также мобильные версии)
Mozilla Firefox не создают контекст наложения в такой ситуации и не считают это необходимым ни для Desktop, ни для Mobile, поскольку не испытывают проблем с оптимизацией скролла.
Internet Explorer (проверил версии 10 и 11) также не формируют контекст наложения для position: fixed
, но комментариев от представителей Microsoft я не нашёл и непонятна их позиция в этом вопросе. У меня не было возможности проверить поведение на Windows Phone и узнать, соответствует ли оно поведению на Desktop. Буду признателен, если кто-то поделится результатом эксперимента.
В любом случае W3C даёт лишь рекомендации, а каждый вендор решает сам для себя следовать им или нет. Нам же, простым разработчикам, остаётся лишь учитывать подобные нюансы в своих веб-приложениях (хорошо, что одна корпорация с небезызвестным продуктом закаляла нас годами).
Благодарю за внимание!
Автор: Toy