Использование возможностей CSS-свойства content-visibility для элементов с динамическим размером

Начальные соображения

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

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

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

Свойство CSS Content-Visibility

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

Браузер выполнит следующий шаг:

  • Загрузка
  • Сценарии
  • Рендеринг
  • Рисование

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

В отличие от дома, где вы можете заняться покраской после завершения строительства — и, возможно, время от времени для заслуженного освежения — у браузера есть много причин для выполнения множества визуализаций с течением времени. Модификации JavaScript DOM, прокрутки, динамические карусели и так далее.

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

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

Как это работает?

Установка этого свойства CSS на auto предотвратит выполнение браузером части рендеринга отображения, что сэкономит много времени выполнения (рендеринг + рисование) для всех скрытых элементов страницы. Затем, как только элементы появятся на экране, будет произведен рендеринг, и вы сможете увидеть свой контент должным образом.

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

Наконец, как только элемент покидает экран, он удаляется из рендеринга вашей страницы. Затем он сохранит другой список потенциально тяжелых вычислений, например, если у вас есть @keyframes анимации.

Установка размера блока

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

Итак, чтобы убедиться, что пространство зарезервировано, вы можете использовать другое свойство CSS, где зарезервируйте это самое пространство при использовании свойства CSS content-visibility: это contain-intrinsic-size, которое вы можете использовать для установки ширины и высоты элементов. content-intrinsic-size: 400px 300px сообщит браузеру, что связанный блок имеет ширину 400 пикселей и высоту 300 пикселей.

Но…

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

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

Будем надеяться, что на помощь придут другие замечательные API в браузере!

Объект IntersectionObserver JavaScript

IntersectionObserver — это API, который определяет, когда блок становится видимым или покидает область просмотра экрана, что почти то же самое, но на этот раз с использованием content-visibility это JavaScript, поэтому он становится более интерактивным и настраиваемым.

У него много замечательных применений, таких как загрузка следующей или предыдущей страницы с бесконечной загрузкой страницы, как только нижний колонтитул попадает в область просмотра, приостановка видео, если вы прокручиваете его за пределы экрана, или ленивая загрузка изображений — даже если вместо этого вы должны использовать loading="lazy".

Как это работает?

Чтобы использовать IntersectionObserver, вам понадобятся три вещи:

  • Функция обратного вызова будет выполняться, когда элемент входит или покидает видимую часть экрана. Здесь произойдет ваше волшебство.
  • Объект наблюдателя, который будет обрабатывать конфигурацию наблюдения, такую ​​как чувствительность обнаружения. Это также означает, что вы можете использовать один и тот же объект конфигурации для каждого блока вашего кода, который вы хотите наблюдать, уменьшая влияние на память.
  • Приложение к объекту DOM, которое мы будем наблюдать. В нашем сценарии это будет блок с динамической высотой, на котором мы не можем использовать свойство content-visibility.

Хватит слов. Вот очень простой пример кода, как начать:

Глубокое погружение в метод обратного вызова

Как вы видели в предыдущем примере, метод обратного вызова принимает два параметра.

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

  • isIntersecting, которое является логическим значением, равным true, отображается в соответствии с конфигурацией false, в противном случае. Это единственная информация, полезная в нашем случае использования, так как мы хотим знать, достиг ли элемент области просмотра и, таким образом, был отрендерен и теперь имеет реальную высоту.
  • target, который является элементом, который в данный момент пересекается. Это будет то же самое, что и объект DOM, который мы прослушали, но поскольку одно IntersectionObserver можно использовать много раз, это свойство более надежно.

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

Теперь давайте посмотрим, как мы можем связать его с content-visibilityfeature.

Блоки обработки с динамическими высотами

Связать IntersectionObserver и content-visibilty теперь очень просто: у нас есть все необходимые инструменты, и мы должны добавить интеллектуальное поведение в метод обратного вызова, чтобы в целом улучшить нашу веб-страницу:

  • Во-первых, мы создаем IntersectionObserver для обнаружения изменений видимости в данном блоке. Когда обнаружение будет выполнено, мы перейдем к методу обратного вызова.
  • Внутри метода обратного вызова мы можем получить фактический размер данного элемента с момента его отображения браузером. Это так же просто, как const { height } = entry.target.getBoundingClientRect();
  • Теперь мы можем установить свойства CSS для объекта. Это однострочник: entry.target.style.containIntrasicSize = `${height}px` . Нет необходимости устанавливать content-visibility: он должен быть уже назначен в вашем CSS, чтобы это работало. Если вы еще этого не сделали, вы потеряете преимущество отсрочки рендеринга.
  • Наконец, поскольку высота теперь задана, нам больше не нужно наблюдение, поэтому мы можем остановить наблюдение на этом блоке.

Вот пример кода, объединяющий эти две функции:

Обработка отзывчивости

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

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

Заключение

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

Если вы работаете с такими фреймворками, как я, вы можете найти хук React и компонуемый Vue, которые вы можете повторно использовать в своих приложениях, в конце этого сообщения в блоге.

Не стесняйтесь давать мне отзывы об улучшениях Core Web Vitals с помощью этого фрагмента!

Реагировать на крючок

Компонуемый Vue

Want to Connect?

If you want to learn more about JavaScript, React and Vue, 
feel free to follow  me on Medium or Twitter.