CSS Containment

в 15:38, , рубрики: containment, css, Разработка веб-сайтов

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

Containment (сдерживание) – новое CSS свойство, позволяющее разработчикам ограничить область применения стилей, компоновок и отрисовок для браузера.

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

contain: none | strict | content | [ size || layout || style || paint ]

Свойство уже есть в браузерах Chrome 52+ и Opera40+, а так же оно публично поддерживается Firefox’ом, поэтому дайте ему шанс и расскажите о том, как это вышло.

Свойство contain

При создании веб-приложения или сложного сайта ключевая задача достижения высокой производительности – это снижение затрат на применения стилей (styles), уменьшение количества компоновок (layout) и отрисовок (paint). Зачастую DOM-дерево целиком оказывается в области пересчёта (scope), что может произойти при хитрой попытке создания автономного объекта (блока) в веб-приложение: в этом случае изменения в одной части DOM-дерева могут повлиять так же на другие элементы, и у разработчика не будет возможности указать браузеру, что должно быть внутри области пересчёта и что – за её пределами.

Рассмотрим пример, допустим часть вашего DOM-дерево выглядит примерно так:

<section class="view">
  Home
</section>
<section class="view">
  About
</section>
<section class="view">
  Contact
</section>

И затем вы добавляете новый элемент к одному из блоков, за чем последует изменение стилей, компоновка и отрисовка:

<section class="view">
  Home
</section>
<section class="view">
  About
  <div class="newly-added-element">Check me out!</div>
</section>
<section class="view">
  Contact
</section>

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

На самом деле всё не так уж и плохо, есть и хорошие новости: современные браузеры становятся умнее и стараются ограничить область применения стилей, компоновки и отрисовки автоматически, и вам не приходится ничего делать, чтобы ускорить эти процессы. Но есть новость и получше: появилось новое CSS свойство, вручающее в руки разработчиков полный контроль над областью – Containment.

CSS Containment – новое свойство, принимающим своим значением одно из 4-х ключевых слов:

  • layout
  • paint
  • size
  • style

Каждое из них позволит вам выбрать, как именно ограничить работу браузера во время рендеринга. Давайте взглянем поближе на эти значения.

Layout (contain: layout)

Это значение включает режим сдерживания компоновки элемента. В таком случае компоновка документа гарантированно не взаимодействует с содержащим блоком: ничего за пределами блока не может повлиять на его внутреннюю компановку и наоборот.

Сдерживание компоновки, возможно, можно считать самым выгодным наряду с contain: paint.

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

Paint (contain: paint)

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

Отрисовка отдельной области — другое чрезвычайно полезное преимущество сдерживания. Управление отрисовкой фактически обрезает элемент (т.е. содержимое невидимо за границами), что влечет за собой несколько побочных эффектов:

  • Для абсолютно и фиксировано позиционированных элементов данный блок действует как сдерживающий блок. Это значает, что любые дети блока позиционируются на основе элемента со свойством contain: paint, но не основе каких-либо других элементов или же всего документа.
  • У элемента создается контекст наложения. Свойство z-index будет влиять на элемент, а все потомки элемента будут наложены согласно новому контексту.
  • Также появляется новый контекст форматирования. К примеру, если у вас есть блочный элемент, у которого задано свойство contain: paint, то он будет рассматриваться как новое и независимое окружение компоновки. Это значит, что компоновка извне не повлияет на содержимое сдерживающего элемента.

Size (contain: size)

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

contain: size запрещает детям элемента влиять на его заданные размеры. Следовательно, если вы установили свойство containt со значением size некоторому элементу, не указав при этом его размеры (напрямую или с помощью flex-свойств), то этот элемент будет отображен с размерами 0px на 0px.

В самом деле, управление размером (сдерживание размера) – надежный способ обеспечить независимость размеров элемента от его потомков, но сам по себе он не дает особых преимуществ.

Style (contain: style)

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

Сложно заранее предугадать, какие эффекты от изменения стилей пойдут вверх по DOM-дереву. Одним из примеров такого поведения — нечто вроде вроде CSS счетчиков, где изменение счетчика у ребенка может повлиять на значения счетчиков с одноименным названием, используемых в другом месте в документе. С заданным contain: style стили заданного элемента не будут распространены дальше вверх по DOM-дереву.

Говоря предельно ясно, чего contain: style не предоставляет вам в отличие от Shadow DOM, так это scoped styling (стили с ограниченной областью видимости). Сдерживание в таком случае подразумевает лишь только ограничение элементов дерева, которые будут рассматриваться при изменении стилей, но не тогда, когда они были объявлены.

Выражаясь предельно ясно, contain: style не предоставляет стили с ограниченной областью видимости (как это работает в Shadow DOM). Сдерживание — это про ограничение кол-ва частей дерева, которые будут учитываться, когда стили будут меняться, а не когда они только объявлены.

Строгое (strict) и содержательное (content) сдерживание

При необходимости вы можете комбинировать значения свойства, к примеру, при contain: layout paint, вы сможете добиться для элемента только таких типов поведения.

Но рассматриваемое в статье свойство так же поддерживает 2 дополнительных значения:

  • contain: strict то же самое, что и contain: layout style paint size
  • contain: content то же самое, что и contain: layout style paint

Использование строгого сдерживания может здорово пригодиться, если вы заранее знаете размеры элемента (или заранее хотите сохранить их), но имейте в виду, что если вы выберите строгое сдерживание без указания размеров из-за предполагаемого размера содержимого, элемент может быть отображен с размерами 0px на 0px.

Сдерживание содержимого, с другой стороны, предлагает значительные улучшения области пересчёта, но не требует от вас знания конкретных размеров элементов заранее. Кстати говоря, contain: content можно использовать по умолчанию.

К более строгим ограничениям прибегайте как к аварийному люку, лишь тогда, когда эффектов от использования contain: content недостаточно в конкретно вашем случае.

Сдерживание – отличный способ указания браузеру, что вы намерены изолировать в пределах вашей страницы. Попробуйте использовать это свойство в Chrome 52+ и расскажите нам, что вы об этом думаете.

Автор: north-elbrus

Источник

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


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