CSS-изоляция
Перевод статьи CSS containment с сайта justmarkup.com, опубликовано на css-live.ru с разрешения автора — Майкла Шарналя
Я узнал про свойство contain
всего несколько недель назад, когда в ответ на мой вопрос в твиттере о применениях медиазапросов для контейнера Дэвид Бэрон упомянул его, сказав, что с contain: strict;
можно избежать множества теоретических проблем с медиазапросами для контейнера. С тех пор я читаю спецификацию, пытаясь понять это свойство, и вот что мне удалось выяснить.
Свойство contain
Это примитивное значение для изоляции стиля, компоновки и отрисовки. Своство contain позволяет разработчикам разграничить конкретное поддерево DOM и остальную часть документа; можете рассматривать его как аналог iframe. Подобно iframe, эта граница устанавливает новый корневой элемент для компоновки, гарантируя, что изменения в поддереве DOM никогда не вызовут перекомпоновки в родительском документе.
Свойство contain позволяет разработчику указать, что элемент со своим содержимым максимально независим от остальной части дерева документа.
Из W3C спецификации
none
| strict
| layout
| style
| paint
| size
| content
У свойства contain
есть семь разных значений.
none
ничего не делаетlayout
включает изоляцию компоновкиstyle
включает изоляцию стиляpaint
включает изоляцию отрисовкиsize
включает изоляцию размеровcontent
всё, кроме изоляции размеровstrict
то же, чтоlayout
,style
,paint
иsize
вместе
Применения
Мы уже знаем, что с этим новым механизмом можно изолировать элементы от остальной части документа, пометив их как независимые части. Вот где это может оказаться полезным:
Виджеты
При подключении сторонних виджетов далеко не всё оказывается в нашей власти, и они могут значительно ухудшить производительность сайта, производя ресурсозатратные операции компоновки, стиля и отрисовки. Чтобы сделать их независимыми от сайта, мы можем установить contain: strict;
самому внешнему элементу стороннего виджета. Таким образом, они не повлияют на производительность всех остальных частей страницы.
За экраном
Если вы делаете навигацию, «выезжающую» из-за экрана, и т.п., браузер отрисовывает содержимое полностью, даже несмотря на то, что его не видно при загрузке. При установке contain: paint;
браузер может пропустить отрисовку того элемента, который находится «вне экрана», и поэтому отрисовка остального содержимого происходит быстрее.
Медиазапросы для контейнера
Как упоминалось в начале, с contain: strict;
можно избежать кучи проблем с медиазапросами для контейнера. Одна из «проблем» медиазапросов для контейнера — дочерние элементы со своим содержимым могут влиять на размер контейнера.
С CSS-изоляцией этого можно избежать.
Почему браузер не может делать это автоматически
Браузерные движки по возможности и так много чего оптимизируют под капотом, но у каждого движка есть свои особенности. Изоляция (containment) даёт стандартный способ, которым приложения указывают браузеру, чтобы тот оптимизировал определённые тонкости компоновки, которые в противном случае он не смог бы оптимизировать.
Итого
Для простых сайтов без кучи DOM-элементов и виджетов, CSS-изоляция, вероятно, не понадобится. Но если сайты сложнее, CSS-изоляция поможет оптимизировать производительность. Также правильным будет установить contain: strict;
для сторонних виджетов, чтобы защитить производительность сайта.
Как обычно — тесты, тесты и ещё раз тесты. И тестировать не только с быстрым интернетом и на дорогих компьютерах, но также и на старых компьютерах и медленным интернетом. Чтобы понять, как другие воспринимают ваш сайт, можно эмулировать скорость сети и процессора с помощью отладчика Chrome.
Примечание: на данный момент (апрель 2016) это свойство поддержвается только в Chrome.
Обновление 06.04.2016: чтобы протестировать CSS-изоляцию, включите флаг chrome://flags/#enable-experimental-web-platform-features в Chrome.
Обновление 20.05.2016: теперь включено по умолчанию в Chrome 52.
Обновление 02.08.2016: добавлены значения «size
» и «content
» из последнего обновления из спецификации.
P.S. Это тоже может быть интересно:
Спасибо!
Отличная статья.
Про такие вещи неплохо бы оставлять в конце ссылку на caniuse
MDN тоже умеет показывать, что это работает только в хроме.
Я понимаю, что это перевод, но было бы здорово, если б было объясненно, что именно понимается под терминами «компановка», «стиль», «отрисовка» и что имеется в виду под изоляцией размеров…
Если очень кратко и поверхностно, то перед выводом картинки на экран браузер проходит 5 стадий, часть из которых может быть опущена: Обработка JS > вычисление стилей > расчет макета > прорисовка > компановка. С начала отрабатывают скрипты, в результате которых картинка может измениться. Далее идет вычисление стилей, чтобы понять, что изменилось и применить данные изменения. В свою очередь это может вызвать расчет макета, если были затронуты свойства, влияющие на размеры и т.п. элемента. После идет прорисовка, если были задеты свойства, вроде изменения цвета, тени и т.п. После идет компановка, то бишь сведение всех измененных слоев в правильном порядке и выведения их на экран пользователя.
Изоляция размеров — тот случай, когда у родителя отсутствует указание размеров, аля `width: auto; height: auto;` и т.п. В таком случае дочерний элемент может повлиять на родительский и изменить (к примеру, увеличить) его размеры. Вот `contain: size;` у родителя как раз и не даст этого сделать.
Ну а по существу, перевод есть перевод и, тем более, первый параграф сего ответа не является целью данной статьи, ибо так статьи излишне распухнет.
Спасибо! Я бы так кратко не объяснил:)
Только в этих вещах еще не очень устоялась русская терминология, во многих материалах (напр. в русской версии классического труда на html5rocks Тали Гарсиэль и Пола Айриша) «компоновкой» называют как раз расчет макета (в оригинале layout, иногда еще reflow), а сведение слоев для вывода на экран называют уже устоявшимся термином «композитинг». В этом переводе под «компоновкой» тоже понимается как раз расчет макета.
Да, вы правы. Отвечал оторвано от перевода. :(
Кстати, в текущих переводах Пола Льюиса на ресурсе-преемнике html5rocks начали использовать термин «компоновка» для обозначения «composite» — https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count?hl=ru. Не знаю, насколько это верно, но в сети упоминание встречается.
От туда же немного о происхождении «layout» / «reflow»: «В браузерах Chrome, Opera, Safari и в Internet Explorer этот процесс называется Layout (Перерасчет макета). В Firefox он называется Reflow (Перерасчет дерева отрисовки), но по сути это один и тот же процесс.» (https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts).
Да, о правильной русской терминологии тут можно спорить долго:). Особенно в связи с многострадальным «layout», который в разных контекстах может быть и «макетом» (как продукт дизайна), и «раскладкой» (как технология, напр. Flexbox layout), и опять же «раскладкой» или той же «компоновкой», но уже как процесс в браузере…
Спасибо за ссылки! Кстати, если употребление этих слов явно меняется, может, есть смысл обновить словарик?
Я вроде бы разбираюсь в технологиях, но не в причудах английского языка. Увы, для меня это больная тема. :)
Спасибо большое за столь содержательный ответ!
Что-то я его пропустил, но всё равно актуален! :)
По статье я понял как раз обратное — есть некий элемент, свойства которого не должны оказывать влияние на РОДИТЕЛЯ (то есть, присваиваем дочернему элементу, что его отрисовывают независимо, чтобы под этим не подразумевалось :-) ).
Всё же, не могли объяснить, на примере тех же размеров, что на что и каким образом влияет?
https://blogs.igalia.com/mrego/2019/01/11/an-introduction-to-css-containment/
https://www.youtube.com/watch?v=iqcO-5_KkJ4