CSS-live.ru

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. Это тоже может быть интересно:

12 комментариев

  1. Я понимаю, что это перевод, но было бы здорово, если б было объясненно, что именно понимается под терминами «компановка», «стиль», «отрисовка» и что имеется в виду под изоляцией размеров…

    1. Если очень кратко и поверхностно, то перед выводом картинки на экран браузер проходит 5 стадий, часть из которых может быть опущена: Обработка JS > вычисление стилей > расчет макета > прорисовка > компановка. С начала отрабатывают скрипты, в результате которых картинка может измениться. Далее идет вычисление стилей, чтобы понять, что изменилось и применить данные изменения. В свою очередь это может вызвать расчет макета, если были затронуты свойства, влияющие на размеры и т.п. элемента. После идет прорисовка, если были задеты свойства, вроде изменения цвета, тени и т.п. После идет компановка, то бишь сведение всех измененных слоев в правильном порядке и выведения их на экран пользователя.

      Изоляция размеров — тот случай, когда у родителя отсутствует указание размеров, аля `width: auto; height: auto;` и т.п. В таком случае дочерний элемент может повлиять на родительский и изменить (к примеру, увеличить) его размеры. Вот `contain: size;` у родителя как раз и не даст этого сделать.

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

      1. Спасибо! Я бы так кратко не объяснил:)

        Только в этих вещах еще не очень устоялась русская терминология, во многих материалах (напр. в русской версии классического труда на html5rocks Тали Гарсиэль и Пола Айриша) «компоновкой» называют как раз расчет макета (в оригинале layout, иногда еще reflow), а сведение слоев для вывода на экран называют уже устоявшимся термином «композитинг». В этом переводе под «компоновкой» тоже понимается как раз расчет макета.

        1. Да, вы правы. Отвечал оторвано от перевода. :(

          Кстати, в текущих переводах Пола Льюиса на ресурсе-преемнике 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).

          1. Да, о правильной русской терминологии тут можно спорить долго:). Особенно в связи с многострадальным «layout», который в разных контекстах может быть и «макетом» (как продукт дизайна), и «раскладкой» (как технология, напр. Flexbox layout), и опять же «раскладкой» или той же «компоновкой», но уже как процесс в браузере…

            Спасибо за ссылки! Кстати, если употребление этих слов явно меняется, может, есть смысл обновить словарик?

            1. Я вроде бы разбираюсь в технологиях, но не в причудах английского языка. Увы, для меня это больная тема. :)

      2. Спасибо большое за столь содержательный ответ!
        Что-то я его пропустил, но всё равно актуален! :)

      3. В таком случае дочерний элемент может повлиять на родительский и изменить (к примеру, увеличить) его размеры. Вот `contain: size;` у родителя как раз и не даст этого сделать.

        По статье я понял как раз обратное — есть некий элемент, свойства которого не должны оказывать влияние на РОДИТЕЛЯ (то есть, присваиваем дочернему элементу, что его отрисовывают независимо, чтобы под этим не подразумевалось :-) ).
        Всё же, не могли объяснить, на примере тех же размеров, что на что и каким образом влияет?

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.