То, что вам никто не говорил о z-index в статье «То, что вам никто не говорил о z-index»

в 7:43, , рубрики: css, Firefox, Google Chrome, html, w3c, Веб-разработка, веб-стандарты, скандалы-интриги-расследования, метки: , , , , ,

image
Почти два года назад вышла статья «What no one told you about z-index» (и её перевод на Хабре «То, что вам никто не говорил о z-index»), авторы которой рассказывают о малоизвестной (76% проголосовавших пользователей Хабра слышат об этом впервые), но документированной возможности создания нового контекста наложения указав opacity меньше единицы.


Но несмотря на название статьи, авторы не рассказали вам ещё кое о чём.

Предполагается, что вы знакомы с понятием контекста наложения (англ. stacking context).

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

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

— Из статьи «То, что вам никто не говорил о z-index». Для понимания темы настоятельно рекомендую к ознакомлению либо её, либо классический труд на MDN.

Новый контекст наложения формируется в случаях:

Рассмотрим последний сценарий более подробно. Он единственный из всего списка не описан стандартами 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) — в этих браузерах обе фигуры будут идентичны.
image

В свою очередь остальные браузеры покажут иную картину.
image

Так получилось потому, что значение 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 (хотя я так и не могу понять, о какой конкретно оптимизации идёт речь и буду признателен если кто-нибудь сможет мне объяснить).

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

On touch-based devices, responsiveness to touch events and in particular scrolling is essential to providing a good user experience. Users really notice if the page is «behind» their finger. As a result, browsers go to great lengths to provide a good scrolling experience. A big part of this is decomposing a web page into portions that move when the page scrolls and portions that do not, then moving these portions relative to each other on a dedicated thread. Stacking contexts render atomically so a page can always be divided into the stuff «behind» the stacking context, the stacking context's content, and the stuff «above» the stacking context (with the minor wrinkle that the background of an element appears «below» its negative z-index children). Elements that are position:fixed but do not form a stacking context are difficult — the browser would like to separate out the parts that do not scroll with the page, but that may include elements that participate in z-index lists of stacking contexts outside the position:fixed subtree. It would be at least in theory possible to detangle this situation, but the complexity is daunting and as far as I know nobody has attempted this yet.

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 формируется в следующих браузерах:

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

Internet Explorer (проверил версии 10 и 11) также не формируют контекст наложения для position: fixed, но комментариев от представителей Microsoft я не нашёл и непонятна их позиция в этом вопросе. У меня не было возможности проверить поведение на Windows Phone и узнать, соответствует ли оно поведению на Desktop. Буду признателен, если кто-то поделится результатом эксперимента.

В любом случае W3C даёт лишь рекомендации, а каждый вендор решает сам для себя следовать им или нет. Нам же, простым разработчикам, остаётся лишь учитывать подобные нюансы в своих веб-приложениях (хорошо, что одна корпорация с небезызвестным продуктом закаляла нас годами).

Благодарю за внимание!

Автор: Toy

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js