Помощь браузерам в оптимизации с помощью свойства CSS contain

Помощь браузерам в оптимизации с помощью свойства CSS contain

От автора: свойство CSS contain дает возможность объяснить макет браузеру, чтобы можно было оптимизировать производительность. Тем не менее, это связано с некоторыми побочными эффектами с точки зрения макета.

В этой статье я собираюсь представить Спецификацию CSS, которая только что стала Рекомендацией W3C. CSS Containment Specification определяет одно свойство — contain, и оно может помочь вам объяснить браузеру, какие части вашего макета являются независимыми и не потребуют пересчета, если какая-то другая часть макета изменится.

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

Проблема пересчета макета

Если вы создаете простые веб-страницы, которые динамически не добавляют или не изменяют элементы после их загрузки с использованием JavaScript, вам не нужно беспокоиться о проблеме, которую решает CSS Containment. Браузеру нужно рассчитать макет только один раз, когда страница загружена.

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

Помощь браузерам в оптимизации с помощью свойства CSS contain

Смотрите исходный пример на CodePen

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

В чем нам помогает contain?

HTML-документ — это древовидная структура, которую можно увидеть при просмотре любого элемента с помощью DevTools. В примере выше, я идентифицирую один элемент, который хочу изменить с помощью JavaScript, а затем вношу некоторые изменения во внутренние компоненты. (Это означает, что я изменяю только вещи внутри поддерева для этого элемента списка.)

Помощь браузерам в оптимизации с помощью свойства CSS contain

Просмотр элемента списка в DevTools

Применение к элементу свойства contain сообщает браузеру, что изменения относятся к поддереву этого элемента, так что браузер может выполнять любые возможные оптимизации — безопасно, зная, что ничего за пределами этого элемента не изменится. Именно то, что может сделать конкретный браузер, зависит от движка. Свойство CSS просто дает вам — как разработчику и эксперту по этому макету — возможность сообщить об этом.

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

Использование contain

Для свойства contain можно установить три различных типа локализации: layout, paint, size.

Примечание: в спецификации уровня 2 есть значение style. Оно было удалено с уровня 1, поэтому не фигурирует в Рекомендации и не реализовано в Firefox.

layout

Значение layout дает наибольшие преимущества. Чтобы включить его, используйте следующий код:

.item { contain: layout;
}

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

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

Для блока устанавливается независимый контекст форматирования. Это гарантирует, что содержимое блока остается в блоке — в частности, будут сохраняться смещения, а поля не будут сворачиваться в блоке. Это то же поведение, которое мы включаем при использовании display: flow-root. Если float может выносить вещи из блока, в результате чего следующий текст будет обтекать их, то есть ситуация, когда элемент меняет расположение вещей вне его, это значение применять не рекомендуется.

Содержащий блок действует как содержащий блок для любых потомков с абсолютной или фиксированной позицией. Это означает, что он будет действовать так, как если бы вы использовали position: relative для блока, к которому вы применили contain: layout.

Блок также создает контекст стекирования. Поэтому z-index будет работать для этого элемента, его потомки будут стекироваться на основе этого нового контекста.

Если мы посмотрим на пример, на этот раз с contain: layout, вы можете увидеть, что когда введен плавающий элемент, он больше не выступает из нижней части окна. Это наш новый Контекст Форматирования Блоков в действии.

Помощь браузерам в оптимизации с помощью свойства CSS contain

Применение contain: layout к содержимому с float (см. пример на CodePen)

paint

Чтобы включить значение paint, используйте следующий код:

.item { contain: paint;
}

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

Значение paint указывает браузеру, что элементы внутри содержащего блока не будут видны за пределами этого блока. Содержимое будет по существу обрезано по границам блока.

Мы можем видеть это на простом примере. Даже если мы зададим карточке высоту, всплывающий элемент все равно выступает из нижней части блока из-за того, что float элемент выведен из потока.

Помощь браузерам в оптимизации с помощью свойства CSS contain

float элемент не содержится в элементе списка

С включенным значением paint float элемент теперь обрезается по размеру блока. Ничто не может быть отрисовано за пределами элемента с contain: paint.

Помощь браузерам в оптимизации с помощью свойства CSS contain

Содержимое блока обрезается до высоты блока (см. пример на CodePen)

size

size — это значение, которое, скорее всего, вызовет у вас проблемы, если вы не до конца знаете, как оно работает. Чтобы применить size, используйте:

.item { contain: size;
}

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

В приведенном ниже примере я не задала высоту li; к ним также применено contain: size. Вы можете видеть, что все элементы свернулись так, как будто у них вообще не было содержимого, что создает очень необычно выглядящий список!

Помощь браузерам в оптимизации с помощью свойства CSS contain

См. пример на CodePen

Если вы зададите высоту блока, то высота будет учитываться при использовании contain: size. Одно только size не создает новый контекст форматирования и, следовательно, не содержит поля, как в случае layout и paint. Менее вероятно, что вы использовали бы его само по себе; скорее всего, вы примените его вместе с другими значениями contain, чтобы получить максимально возможную локализацию.

Сокращенные значения

В большинстве случаев вы можете использовать одно из двух сокращенных значений. Чтобы включить layout и paint, используйте contain: content;, а чтобы включить все возможные значения (имея в виду, что элементы, которые не имеют размера, будут свернуты), используйте contain: strict.

Спецификация гласит: «contain: content достаточно «безопасно» для широкого применения; его эффекты довольно незначительны на практике, и большая часть контента не будет противоречить его ограничениям. Однако, поскольку он не применяет ограничение размера, элемент все равно может реагировать на размер своего содержимого, что может привести к тому, что аннулирование макета распространится по дереву вверх дальше, чем требуется. Используйте, contain: strict когда это возможно».

Поэтому, если вы заранее не знаете размер элемента и понимаете, что поля будут ограничены, используйте contain: content. Если вы знаете размер элементов в дополнение к тому, что вы не имеете ничего против других побочные эффектов, используйте contain: strict. Остальное зависит от браузера.

Могу ли я использовать это сейчас?

Спецификация CSS Containment теперь является Рекомендацией W3C, которую мы иногда называем веб-стандартом. Чтобы спецификация достигла этого этапа, необходимо было две реализации этой функции, которые мы можем видеть как в Firefox, так и в Chrome:

Помощь браузерам в оптимизации с помощью свойства CSS contain

Поддержка браузерами (Источник: Can I Use)

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

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

Поэтому, если у вас есть страница, которая добавляет контент в DOM после загрузки, я бы рекомендовала попробовать — если вы получите какие-либо интересные результаты, дайте мне знать в комментариях!

Автор: Rachel Andrew

Источник: https://www.smashingmagazine.com

Редакция: Команда webformyself.