Неожиданные изменения макета могут нарушить работу пользователя во многих отношениях: от того, что он потеряет свое место во время чтения, если текст внезапно перемещается, до того, что он заставит его щелкнуть неправильную ссылку или кнопку. В некоторых случаях это может нанести серьезный ущерб.
Неожиданное перемещение содержимого страницы обычно происходит, когда ресурсы загружаются асинхронно или элементы DOM динамически добавляются на страницу перед существующим контентом. Причиной изменений макета могут быть изображения или видео с неизвестными размерами, шрифты, которые отображаются больше или меньше, чем исходный резервный вариант, или сторонние объявления или виджеты, которые динамически изменяют свой размер.
Различия между тем, как сайт функционирует в процессе разработки, и тем, как его воспринимают пользователи, усугубляют эту проблему. Например:
- Персонализированный или сторонний контент часто ведет себя по-разному при разработке и производстве.
- Тестовые изображения часто уже находятся в кеше браузера разработчика, но загрузка у конечного пользователя занимает больше времени.
- Вызовы API, выполняемые локально, часто выполняются настолько быстро, что незаметные задержки в разработке могут стать существенными в производстве.
Метрика «Совокупный сдвиг макета» (CLS) помогает решить эту проблему, измеряя, как часто она возникает у реальных пользователей.
Что такое ЦЛС?
CLS — это показатель наибольшего количества изменений макета для каждого неожиданного изменения макета, которое происходит в течение всего жизненного цикла страницы.
Сдвиг макета происходит каждый раз, когда видимый элемент меняет свое положение от одного визуализированного кадра к другому. (Подробнее о том, как рассчитываются баллы за сдвиг индивидуальной компоновки, описано далее в этом руководстве.)
Серия изменений макета, известная как окно сеанса , — это когда одно или несколько отдельных изменений макета происходят в быстрой последовательности с интервалом менее 1 секунды между каждым сдвигом и максимум 5 секундами в течение всей продолжительности окна.
Самый большой всплеск — это окно сеанса с максимальным совокупным баллом всех сдвигов макета в этом окне.
Что такое хороший показатель CLS?
Чтобы обеспечить хороший пользовательский опыт, сайты должны стремиться иметь показатель CLS 0,1 или меньше. Чтобы гарантировать достижение этой цели для большинства ваших пользователей, хорошим порогом для измерения является 75-й процентиль загрузки страниц, сегментированный по мобильным и настольным устройствам.
Дополнительные сведения об исследованиях и методологии, лежащих в основе этой рекомендации, см. в разделе Определение пороговых значений показателей Core Web Vitals .
Изменения макета в деталях
Сдвиги макета определяются с помощью Layout Instability API , который сообщает записи layout-shift
каждый раз, когда элемент, видимый в области просмотра, меняет свою начальную позицию (например, верхнюю и левую позиции в режиме записи по умолчанию) между двумя кадрами. Такие элементы считаются нестабильными элементами .
Обратите внимание, что сдвиги макета происходят только тогда, когда существующие элементы меняют свое начальное положение. Если в DOM добавляется новый элемент или размер существующего элемента изменяется, это не считается сдвигом макета — до тех пор, пока это изменение не приводит к изменению исходного положения других видимых элементов.
Оценка смещения макета
Чтобы вычислить показатель смещения макета , браузер смотрит на размер области просмотра и перемещение нестабильных элементов в области просмотра между двумя отображаемыми кадрами. Оценка смещения компоновки является произведением двух показателей этого перемещения: доли воздействия и доли расстояния (оба определены ниже).
layout shift score = impact fraction * distance fraction
Ударная фракция
Доля воздействия измеряет, насколько нестабильные элементы влияют на область просмотра между двумя кадрами.
Доля воздействия для данного кадра представляет собой комбинацию видимых площадей всех нестабильных элементов для этого кадра и предыдущего кадра как часть общей площади области просмотра.
![Пример ударной доли с одним нестабильным элементом](https://web.dev/static/articles/cls/image/impact-fraction-example-164341c82ee76.png?authuser=5&hl=ru)
На предыдущем изображении есть элемент, который занимает половину области просмотра в одном кадре. Затем в следующем кадре элемент смещается вниз на 25 % высоты области просмотра. Красный пунктирный прямоугольник указывает на объединение видимой области элемента в обоих кадрах, что в данном случае составляет 75 % от общей области просмотра, поэтому его доля воздействия равна 0.75
.
Доля расстояния
Другая часть уравнения оценки смещения макета измеряет расстояние, на которое нестабильные элементы переместились относительно области просмотра. Доля расстояния — это наибольшее расстояние по горизонтали или вертикали, на которое переместился любой нестабильный элемент в кадре, разделенное на наибольший размер области просмотра (ширину или высоту, в зависимости от того, что больше).
![Пример доли расстояния с одним нестабильным элементом](https://web.dev/static/articles/cls/image/distance-fraction-example-9146d2a862482.png?authuser=5&hl=ru)
В предыдущем примере наибольший размер области просмотра — это высота, а нестабильный элемент переместился на 25 % высоты области просмотра, что составляет долю расстояния 0,25.
Итак, в этом примере доля воздействия равна 0.75
, а доля расстояния — 0.25
, поэтому показатель смещения макета составляет 0.75 * 0.25 = 0.1875
.
Примеры
Следующий пример иллюстрирует, как добавление контента к существующему элементу влияет на оценку сдвига макета:
![Пример смены компоновки с несколькими стабильными и _нестабильными элементами_](https://web.dev/static/articles/cls/image/layout-shift-example-mul-10d90b67b5d6a.png?authuser=5&hl=ru)
В этом примере серый прямоугольник меняет размер, но его начальная позиция не меняется, поэтому это не нестабильный элемент .
Программа «Нажми на меня!» кнопки ранее не было в DOM, поэтому ее начальная позиция также не меняется.
Однако начальное положение зеленого поля меняется, но поскольку оно частично перемещено за пределы области просмотра, невидимая область не учитывается при расчете доли воздействия . Объединение видимых областей зеленого прямоугольника в обоих кадрах (показано красным пунктирным прямоугольником) такое же, как площадь зеленого прямоугольника в первом кадре — 50% области просмотра. Ударная фракция составляет 0.5
.
Доля расстояния показана фиолетовой стрелкой. Зеленый прямоугольник переместился вниз примерно на 14% области просмотра, поэтому доля расстояния равна 0.14
.
Оценка смещения макета составляет 0.5 x 0.14 = 0.07
.
В следующем примере показано, как несколько нестабильных элементов влияют на показатель смещения макета страницы:
![Пример смещения макета со стабильными и _нестабильными элементами_ и обрезкой области просмотра](https://web.dev/static/articles/cls/image/layout-shift-example-sta-05cf93597fcee.png?authuser=5&hl=ru)
В первом кадре предыдущего изображения показаны четыре результата запроса API для животных, отсортированные в алфавитном порядке. Во втором кадре к отсортированному списку добавляются дополнительные результаты.
Первый элемент в списке («Кошка») не меняет свою начальную позицию между кадрами, поэтому он стабилен. Аналогично, новые элементы, добавленные в список, ранее не были в DOM, поэтому их начальные позиции также не меняются. Но предметы с пометками «Собака», «Лошадь» и «Зебра» меняют свое исходное положение, что делает их нестабильными элементами .
Опять же, красные пунктирные прямоугольники представляют собой объединение этих трех нестабильных элементов «до» и «после» областей, которые в данном случае составляют около 60% площади области просмотра ( коэффициент воздействия 0.60
).
Стрелки обозначают расстояния, на которые нестабильные элементы переместились со своих исходных позиций. Элемент «Зебра», представленный синей стрелкой, сместился больше всего, примерно на 30 % высоты области просмотра. Это делает долю расстояния в этом примере равной 0.3
.
Оценка смещения макета составляет 0.60 x 0.3 = 0.18
.
Ожидаемые и неожиданные изменения макета
Не все изменения макета плохи. Фактически, многие динамические веб-приложения часто меняют начальное положение элементов на странице. Сдвиг макета плох только в том случае, если пользователь этого не ожидает.
Изменения макета по инициативе пользователя
Сдвиги макета, которые происходят в ответ на действия пользователя (например, щелчок или касание ссылки, нажатие кнопки или ввод текста в поле поиска), как правило, допустимы, если сдвиг происходит достаточно близко к взаимодействию, чтобы взаимосвязь была ясна. Пользователь.
Например, если взаимодействие с пользователем запускает сетевой запрос, выполнение которого может занять некоторое время, лучше сразу освободить немного места и отобразить индикатор загрузки, чтобы избежать неприятного изменения макета после завершения запроса. Если пользователь не осознает, что что-то загружается, или не знает, когда ресурс будет готов, он может попытаться щелкнуть что-нибудь еще во время ожидания — что-то, что может выйти из-под него.
Для сдвигов макета, которые происходят в течение 500 миллисекунд после ввода пользователя, будет установлен флаг hadRecentInput
, поэтому их можно исключить из вычислений.
Анимации и переходы
Анимации и переходы, если они выполнены правильно, являются отличным способом обновить контент на странице, не удивляя пользователя. Контент, который резко и неожиданно меняется на странице, почти всегда создает плохой пользовательский опыт. Но контент, который постепенно и естественно перемещается из одной позиции в другую, часто может помочь пользователю лучше понять, что происходит, и направлять его между изменениями состояний.
Обязательно соблюдайте настройки браузера prefers-reduced-motion
, так как некоторые посетители сайта могут испытывать неприятные последствия или проблемы с вниманием из-за анимации.
Свойство transform
CSS позволяет анимировать элементы, не вызывая сдвигов макета:
- Вместо изменения свойств
height
иwidth
используйтеtransform: scale()
. - Чтобы перемещать элементы, избегайте изменения свойств
top
,right
,bottom
илиleft
и вместо этого используйтеtransform: translate()
.
Как измерить CLS
CLS можно измерить в лаборатории или в полевых условиях , и он доступен в следующих инструментах:
Полевые инструменты
- Отчет об опыте использования Chrome
- Статистика PageSpeed
- Search Console (отчет «Основные веб-показатели»)
- JavaScript-библиотека
web-vitals
Лабораторные инструменты
Измерение изменений макета в JavaScript
Чтобы измерить изменения макета в JavaScript, вы используете Layout Instability API .
В следующем примере показано, как создать PerformanceObserver
для регистрации записей layout-shift
в консоли:
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('Layout shift:', entry);
}
}).observe({type: 'layout-shift', buffered: true});
Измерение CLS в JavaScript
Чтобы измерить CLS в JavaScript, вам необходимо сгруппировать эти неожиданные записи layout-shift
в сеансы и вычислить максимальное значение сеанса. Вы можете обратиться к исходному коду библиотеки JavaScript web vitals
, который содержит эталонную реализацию расчета CLS.
В большинстве случаев текущее значение CLS на момент выгрузки страницы является окончательным значением CLS для этой страницы, но есть несколько важных исключений, о которых говорится в следующем разделе. Библиотека JavaScript web vitals
учитывает их в максимально возможной степени в рамках ограничений веб-API.
Различия между метрикой и API
- Если страница загружается в фоновом режиме или находится в фоновом режиме до того, как браузер отрисовывает какой-либо контент, она не должна сообщать никаких значений CLS.
- Если страница восстанавливается из обратного/прямого кэша , ее значение CLS должно быть сброшено до нуля, поскольку пользователи воспринимают это как отдельное посещение страницы.
- API не сообщает записи
layout-shift
для изменений, которые происходят внутри iframe, но метрика делает это, поскольку они являются частью взаимодействия пользователя со страницей. Это может проявляться как разница между CrUX и RUM . Чтобы правильно измерить CLS, вам следует их учитывать. Подкадры могут использовать API для передачи своих записейlayout-shift
родительскому кадру для агрегирования .
В дополнение к этим исключениям, CLS имеет некоторую дополнительную сложность из-за того, что он измеряет весь срок жизни страницы:
- Пользователи могут держать вкладку открытой в течение очень долгого времени — дней, недель, месяцев. Фактически, пользователь может никогда не закрыть вкладку.
- В мобильных операционных системах браузеры обычно не запускают обратные вызовы выгрузки страницы для фоновых вкладок, что затрудняет сообщение «окончательного» значения.
Чтобы справиться с такими случаями, о CLS следует сообщать каждый раз, когда страница находится в фоновом режиме, а также каждый раз, когда она выгружается ( событие visibilitychange
охватывает оба этих сценария). А системам аналитики, получающим эти данные, затем необходимо будет рассчитать окончательное значение CLS на бэкэнде.
Вместо того, чтобы запоминать и разбираться со всеми этими случаями самостоятельно, разработчики могут использовать библиотеку JavaScript web-vitals
для измерения CLS, которая учитывает все, упомянутое выше, за исключением случая iframe:
import {onCLS} from 'web-vitals';
// Measure and log CLS in all situations
// where it needs to be reported.
onCLS(console.log);
Как улучшить CLS
Дополнительные рекомендации по выявлению изменений в компоновке на местах и использованию лабораторных данных для их оптимизации см. в нашем руководстве по оптимизации CLS .
Дополнительные ресурсы
- Рекомендации Google Publisher Tag по минимизации смещения макета
- Понимание совокупного изменения макета , Энни Салливан и Стив Кобес на #PerfMatters (2020)
Журнал изменений
Иногда ошибки обнаруживаются в API, используемых для измерения метрик, а иногда и в определениях самих метрик. В результате иногда приходится вносить изменения, и эти изменения могут проявляться в виде улучшений или регрессов в ваших внутренних отчетах и информационных панелях.
Чтобы помочь вам справиться с этим, все изменения в реализации или определении этих показателей будут отражены в этом журнале изменений .
Если у вас есть отзывы по этим показателям, вы можете оставить их в группе Google web-vitals-feedback .