content-visibility: новое свойство CSS, которое повышает производительность рендеринга.

Уменьшите время начальной загрузки, пропустив рендеринг закадрового контента.

Свойство content-visibility , появившееся в Chromium 85, может стать одним из наиболее эффективных новых свойств CSS для повышения производительности загрузки страниц. content-visibility позволяет пользовательскому агенту пропускать работу по рендерингу элемента, включая макет и рисование, до тех пор, пока он не понадобится. Поскольку рендеринг пропускается, если большая часть вашего контента находится за кадром, использование свойства content-visibility значительно ускоряет начальную загрузку пользователя. Это также позволяет быстрее взаимодействовать с контентом на экране. Довольно аккуратно.

демо с цифрами, представляющими результаты сети
В нашей демонстрационной статье применение content-visibility: auto к фрагментированным областям контента дает 7-кратный прирост производительности рендеринга при начальной загрузке. Читайте дальше, чтобы узнать больше.

Поддержка браузера

Поддержка браузера

  • Хром: 85.
  • Край: 85.
  • Фаерфокс: 125.
  • Сафари: 18.

Источник

content-visibility опирается на примитивы из спецификации CSS Containment Spec . Хотя content-visibility на данный момент поддерживается только в Chromium 85 (и считается «достойной создания прототипа» для Firefox), спецификация Containment Spec поддерживается в большинстве современных браузеров .

CSS-сдерживание

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

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

Существует четыре типа CSS-содержания , каждый из которых представляет собой потенциальное значение свойства CSS- contain , которое можно объединить в список значений, разделенных пробелами:

  • size : ограничение размера элемента гарантирует, что блок элемента можно будет разместить без необходимости проверки его потомков. Это означает, что мы потенциально можем пропустить размещение потомков, если все, что нам нужно, это размер элемента.
  • layout : сдерживание макета означает, что потомки не влияют на внешний макет других блоков на странице. Это позволяет нам потенциально пропустить размещение потомков, если все, что мы хотим сделать, это расположить другие блоки.
  • style : Включение стиля гарантирует, что свойства, которые могут влиять не только на его потомков, не выходят за пределы элемента (например, счетчики). Это позволяет нам потенциально пропустить вычисление стилей для потомков, если все, что нам нужно, — это вычислить стили для других элементов.
  • paint : сдерживание рисования гарантирует, что потомки содержащего блока не будут отображаться за его пределами. Ничто не может явно переполнять элемент, и если элемент находится за пределами экрана или по какой-либо причине не виден, его потомки также не будут видны. Это позволяет нам потенциально пропустить рисование потомков, если элемент находится за кадром.

Пропуск работы по рендерингу с помощью content-visibility

Может быть сложно определить, какие значения ограничения использовать, поскольку оптимизация браузера может начаться только тогда, когда указан соответствующий набор. Вы можете поиграть со значениями, чтобы увидеть , что работает лучше всего , или вы можете использовать другое свойство CSS, называемое content-visibility для автоматического применения необходимого ограничения. content-visibility гарантирует, что вы получите максимальный прирост производительности, который может обеспечить браузер, с минимальными усилиями со стороны вас как разработчика.

Свойство content-visibility принимает несколько значений, но значение auto обеспечивает немедленное повышение производительности. Элемент с content-visibility: auto получает layout , style и включение paint . Если элемент находится за пределами экрана (и не имеет никакого отношения к пользователю иначе — релевантными элементами будут те, которые имеют фокус или выделение в своем поддереве), он также получает ограничение size (и перестает рисовать и проверять его содержимое).

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

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

Примечание о доступности

Одной из особенностей content-visibility: auto является то, что содержимое за кадром остается доступным в объектной модели документа и, следовательно, в дереве доступности (в отличие от visibility: hidden ). Это означает, что контент можно искать на странице и переходить к нему, не дожидаясь его загрузки и не жертвуя производительностью рендеринга.

Однако обратной стороной этого является то, что элементы -ориентиры с такими функциями стиля, как display: none или visibility: hidden также будут отображаться в дереве специальных возможностей, когда они находятся за пределами экрана, поскольку браузер не будет отображать эти стили до тех пор, пока они не войдут в область просмотра. . Чтобы они не были видны в дереве доступности и не могли вызвать беспорядок, обязательно добавьте также aria-hidden="true" .

Пример: блог о путешествиях.

В этом примере мы размещаем наш блог о путешествиях справа и применяем content-visibility: auto к фрагментированным областям слева. Результаты показывают, что время рендеринга увеличивается с 232 мс до 30 мс при начальной загрузке страницы.

Блог о путешествиях обычно содержит набор историй с несколькими изображениями и описательным текстом. Вот что происходит в обычном браузере при переходе на блог о путешествиях:

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

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

Скриншот туристического блога.
Пример туристического блога. См. демо на Codepen

Теперь представьте, что произойдет, если вы установите content-visibility: auto для каждой отдельной истории в блоге. Общий цикл тот же: браузер загружает и отображает фрагменты страницы. Однако разница заключается в объеме работы, которую он выполняет на этапе 2.

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

Производительность загрузки этой страницы будет такой, как если бы она содержала полные экранные истории и пустые поля для каждой из закадровых историй. Это работает намного лучше, с ожидаемым снижением затрат на рендеринг при загрузке на 50% или более . В нашем примере мы видим увеличение времени рендеринга с 232 мс до 30 мс . Это семикратный прирост производительности.

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

Скриншот с аннотациями, на котором показано разделение контента на разделы с помощью класса CSS.
Пример разделения контента на разделы с применением класса story для получения content-visibility: auto . См. демо на Codepen

Затем мы применяем к разделам следующее правило стиля:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Указание естественного размера элемента с помощью contain-intrinsic-size

Чтобы реализовать потенциальные преимущества content-visibility , браузеру необходимо применить ограничение размера, чтобы гарантировать, что результаты рендеринга содержимого никоим образом не влияют на размер элемента. Это означает, что элемент будет располагаться так, как если бы он был пустым. Если для элемента не указана высота в обычном блочном макете, то его высота будет равна 0.

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

К счастью, CSS предоставляет еще одно свойство, contain-intrinsic-size , которое эффективно определяет естественный размер элемента , если на элемент влияет ограничение размера . В нашем примере мы устанавливаем значение 1000px в качестве оценки высоты и ширины разделов.

Это означает, что он будет располагаться так, как если бы у него был один дочерний элемент с размерами «внутреннего размера», гарантируя, что ваши неразмерные элементы div по-прежнему будут занимать место. contain-intrinsic-size действует как размер заполнителя вместо отображаемого контента.

В Chromium 98 и более поздних версиях появилось новое ключевое слово auto для contain-intrinsic-size . Если этот параметр указан, браузер запомнит последний отображаемый размер, если таковой имеется, и будет использовать его вместо размера заполнителя, предоставленного разработчиком. Например, если вы указали contain-intrinsic-size: auto 300px , элемент начнет иметь внутренний размер 300px в каждом измерении, но как только содержимое элемента будет визуализировано, он сохранит визуализированный внутренний размер. Любые последующие изменения размера рендеринга также будут запомнены. На практике это означает, что если вы прокрутите элемент с применением content-visibility: auto , а затем прокрутите его обратно за пределы экрана, он автоматически сохранит идеальную ширину и высоту и не вернется к размеру заполнителя. Эта функция особенно полезна для бесконечных скроллеров, которые теперь могут автоматически улучшать оценку размера с течением времени по мере того, как пользователь исследует страницу.

Скрытие контента с помощью content-visibility: hidden

Что, если вы хотите, чтобы контент оставался необработанным независимо от того, отображается он на экране или нет, используя при этом преимущества кэшированного состояния рендеринга? Введите: content-visibility: hidden .

Свойство content-visibility: hidden дает вам все те же преимущества неотрисованного контента и кэшированного состояния рендеринга, что и content-visibility: auto за пределами экрана. Однако, в отличие от auto , он не начинает автоматически рендеринг на экране.

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

Сравните его с другими распространенными способами сокрытия содержимого элемента:

  • display: none : скрывает элемент и уничтожает его состояние рендеринга. Это означает, что отобразить элемент так же дорого, как отобразить новый элемент с тем же содержимым.
  • visibility: hidden : скрывает элемент и сохраняет его состояние рендеринга. На самом деле это не удаляет элемент из документа, поскольку он (и его поддерево) по-прежнему занимает геометрическое пространство на странице, и на него по-прежнему можно щелкнуть. Он также обновляет состояние рендеринга в любое время, даже если оно скрыто.

content-visibility: hidden , с другой стороны, скрывает элемент, сохраняя при этом состояние его рендеринга, поэтому, если есть какие-либо изменения, которые должны произойти, они происходят только тогда, когда элемент отображается снова (т.е. свойство content-visibility: hidden удаляется).

Некоторые отличные варианты использования content-visibility: hidden — при реализации расширенных виртуальных скроллеров и измерении макета. Они также отлично подходят для одностраничных приложений (SPA). Неактивные представления приложений можно оставить в DOM с применением content-visibility: hidden чтобы предотвратить их отображение, но сохранить их кэшированное состояние. Это ускоряет визуализацию представления, когда оно снова становится активным.

Влияние на взаимодействие со следующей отрисовкой (INP)

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

Всякий раз, когда вы можете сократить объем работы по рендерингу на какой-либо странице, вы даете основному потоку возможность быстрее реагировать на вводимые пользователем данные. Это включает в себя работу по рендерингу, а использование свойства CSS content-visiblity где это необходимо, может сократить работу по рендерингу, особенно во время запуска, когда большая часть работы по рендерингу и макету уже выполнена.

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

Заключение

content-visibility и спецификация CSS Containment Spec означают, что ваш CSS-файл получит впечатляющее повышение производительности. Для получения дополнительной информации об этих свойствах посетите: