Уменьшите объем и сложность расчетов стилей.

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

Расчет стиля

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

Браузер начинает вычислять стили, создавая набор соответствующих селекторов, чтобы определить, какие классы, псевдоселекторы и идентификаторы применяются к любому данному элементу. Затем он обрабатывает правила стилей из соответствующих селекторов и выясняет, какие окончательные стили имеет элемент.

Роль пересчета стиля в задержке взаимодействия

Interaction to Next Paint (INP) — это ориентированная на пользователя метрика производительности выполнения, которая оценивает общую отзывчивость страницы на пользовательский ввод. Она измеряет задержку взаимодействия с момента, когда пользователь взаимодействует со страницей, до момента, когда браузер отрисовывает следующий кадр, показывая соответствующие визуальные обновления пользовательского интерфейса.

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

Уменьшите сложность ваших селекторов

Упрощение селекторов CSS может помочь ускорить расчеты стилей вашей страницы. Простейшие селекторы ссылаются на элемент в CSS только с именем класса:

.title {
  /* styles */
}

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

.box:nth-last-child(-n+1) .title {
  /* styles */
}

Чтобы определить, как эти стили применяются к странице, браузер должен фактически спросить: «Это элемент с классом title , родительский элемент которого имеет класс box , который является минус-n-ным-плюс-1 дочерним элементом своего родительского элемента?». Выяснение этого может занять некоторое время у браузера. Чтобы упростить этот процесс, вы можете изменить селектор на более конкретное имя класса:

.final-box-title {
  /* styles */
}

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

Уменьшите количество стилизуемых элементов

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

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

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

Измерьте стоимость перерасчета вашего стиля

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

Измерение стоимости пересчета стиля в Chrome DevTools

Один из способов измерить стоимость пересчета стилей — использовать панель производительности в Chrome DevTools. Для начала выполните следующие действия:

  1. Откройте DevTools.
  2. Перейдите на вкладку «Производительность» .
  3. Установите флажок Статистика селектора (необязательно).
  4. Нажмите «Запись» .
  5. Взаимодействуйте со страницей.

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

DevTools показывает расчеты стилей.
Отчет DevTools, показывающий расчеты стилей.

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

Увеличение проблемной области в Chrome DevTools в сводке активности заполненной панели производительности в Chrome DevTools.
Длительные кадры в сводке активности DevTools.

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

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

При нажатии на событие отображается его стек вызовов. Если работа по рендерингу была вызвана взаимодействием с пользователем, он вызывает JavaScript, который вызвал изменение стиля. Он также показывает количество элементов, на которые влияет изменение (в данном случае чуть более 900 элементов), и сколько времени заняло вычисление стиля. Вы можете использовать эту информацию, чтобы начать пытаться найти исправление в своем коде.

Если перед выполнением трассировки вы отметили флажок «Статистика селектора» в настройках панели «Производительность» , то на нижней панели трассировки появится дополнительная вкладка с тем же названием.

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

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

Более подробную информацию см. в документации по CSS Selector Stats .

Стоимость пересчета стиля измерения для реальных пользователей

Если вам интересно узнать, сколько времени требуется для пересчета стиля для реальных пользователей вашего веб-сайта, API Long Animation Frames предоставляет вам необходимые для этого инструменты. Данные из этого API были добавлены в библиотеку JavaScript web-vitals , включая время пересчета стиля.

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

Ресурсы