Core Web Vitals: полный обзор
Что измеряют LCP, INP и CLS, пороги, двенадцать причин плохих метрик с решениями, полевые и лабораторные данные, четыре примера с цифрами до и после, ошибки и правила.
Коротко
Core Web Vitals — три метрики Google, которые описывают, какой страница кажется живому посетителю: LCP — как быстро появляется главное содержимое, INP — как быстро страница отвечает на клики и касания, CLS — насколько прыгает раскладка. Страница проходит, когда 75% настоящих визитов укладываются в пороги: LCP до 2,5 секунды, INP до 200 миллисекунд, CLS до 0,1. Google учитывает их в поиске как часть удобства страницы, но главная ценность в другом: быстрая и устойчивая страница удерживает людей и больше продаёт. Большинство проблем идёт от нескольких причин — тяжёлые картинки, шрифты, скрипты и медленный сервер.
Core Web Vitals коротко
Главные факты одной таблицей: что измеряется, как оценивается страница и откуда берутся данные.
- Что это
- Метрики Google для реального опыта посетителя: загрузка, отклик, устойчивость
- Метрики
- LCP, INP, CLS; INP заменил FID в марте 2024 года
- Как оценивается
- 75-й процентиль настоящих визитов за 28 дней, отдельно для телефонов и компьютеров
- Источник данных
- Отчёт Chrome User Experience Report (CrUX) — обезличенные данные пользователей Chrome
- Где смотреть
- PageSpeed Insights, Search Console, Chrome DevTools
- В поиске
- Часть сигналов удобства страницы с 2021 года; соответствие содержимого запросу по-прежнему важнее
- Свой замер
- Библиотека web-vitals от Google — те же цифры от ваших собственных посетителей
Метрики и их пороги
Три Core Web Vitals и две вспомогательные метрики, которые их объясняют. Пороги взяты из библиотеки web-vitals от Google.
| Метрика | Что измеряет | Хорошо | Требует работы | Плохо |
|---|---|---|---|---|
| LCP | когда появляется самый крупный элемент первого экрана | до 2,5 с | 2,5–4 с | больше 4 с |
| INP | сколько клик или касание ждёт видимого ответа | до 200 мс | 200–500 мс | больше 500 мс |
| CLS | насколько раскладка сдвигается сама | до 0,1 | 0,1–0,25 | больше 0,25 |
| FCP | когда появляется хоть что-то — вспомогательная | до 1,8 с | 1,8–3 с | больше 3 с |
| TTFB | когда сервер начинает отвечать — вспомогательная | до 0,8 с | 0,8–1,8 с | больше 1,8 с |
Что портит метрики и как это исправить
Двенадцать частых причин — с метрикой, которую они бьют, и решением.
| Причина | Метрика | Решение |
|---|---|---|
| Тяжёлая картинка на первом экране | LCP | AVIF или WebP, srcset, fetchpriority="high" |
| Картинка первого экрана грузится лениво | LCP | убрать у неё loading="lazy" |
| Медленный ответ сервера | LCP | кэш, меньше запросов к базе, CDN |
| Шрифты со стороннего сервиса | LCP | свои файлы woff2 с подрезкой |
| Содержимое рисует JavaScript | LCP | отдавать HTML с сервера |
| Долгие задачи в обработчиках кликов | INP | сначала отрисовать реакцию, потом работать |
| Тяжёлые сторонние скрипты | INP | загружать позже или убрать |
| Огромный DOM | INP | меньше элементов, content-visibility |
| Картинки без размеров | CLS | width и height в HTML |
| Поздно загружаемые баннеры и виджеты | CLS | зарезервированное место через min-height |
| Веб-шрифт заменяет запасной | CLS | подогнанный запасной шрифт или font-display: optional |
| Анимации top и height | CLS | анимировать transform и opacity |
Полевые и лабораторные данные
-
Полевые данные
Настоящие визиты из CrUX — именно их Google использует в поиске и показывает в Search Console.
-
Лабораторные данные
Один прогон Lighthouse на эмулированном телефоне — хорош для поиска причин, но не для итоговой оценки.
-
Почему они расходятся
У настоящих посетителей разные телефоны, сети и страницы; в лаборатории — одно устройство и одна загрузка.
-
INP в лаборатории
Lighthouse не кликает, поэтому показывает Total Blocking Time — подсказку, а не сам INP.
-
28 дней задержки
Полевые данные собираются за 28 дней — исправление полностью видно в отчётах примерно через месяц.
-
Небольшие сайты
При малом трафике в CrUX нет данных — тогда помогает собственный замер через web-vitals.
Замер и исправления: 4 примера
Собственный замер и по одному исправлению на каждую метрику. Каждый пример проверен в браузере на тестовом стенде, с цифрами до и после.
Свои полевые данные
После клика и закрытия вкладки сервер получил все три метрики с оценками.
// Метрики настоящих посетителей: измеряются в их браузерах, собираются на нашем сервере
import { onCLS, onINP, onLCP } from 'web-vitals';
function send(metric) {
const body = JSON.stringify({
name: metric.name, // LCP, INP или CLS
value: metric.value, // миллисекунды; у CLS — оценка без единиц
rating: metric.rating, // good, needs-improvement или poor
page: location.pathname,
});
// sendBeacon переживает закрытие вкладки — именно тогда INP и CLS становятся окончательными
if (!navigator.sendBeacon('/api/vitals', body)) {
fetch('/api/vitals', { method: 'POST', body, keepalive: true });
}
}
onLCP(send);
onINP(send);
onCLS(send);
LCP: картинка первого экрана
Главная картинка запрашивается с приоритетом High и становится элементом LCP; нижняя запрашивается только после прокрутки.
<!-- Картинка первого экрана: браузер грузит её первой и никогда не лениво -->
<img src="/img/hero-1200.avif"
srcset="/img/hero-800.avif 800w, /img/hero-1200.avif 1200w"
sizes="(max-width: 800px) 100vw, 1200px"
width="1200" height="630" alt="Дубовый стол на светлой кухне"
fetchpriority="high">
<!-- Картинки ниже: грузятся, только когда человек до них докрутит -->
<img src="/img/table-top.webp" width="600" height="400"
alt="Столешница из дуба крупным планом" loading="lazy" decoding="async">
CLS: зарезервированное место
Одна и та же страница с поздней картинкой, плеером и промоблоком: CLS 0,326 без этих правил и 0 с ними.
/* Место резервируется до того, как придёт содержимое, — ничего ниже не прыгает */
img,
video {
max-width: 100%;
height: auto; /* пропорции берутся из width и height в HTML */
}
.embed {
aspect-ratio: 16 / 9; /* видеоплееры, карты и другие iframe */
}
.embed > iframe {
width: 100%;
height: 100%;
border: 0;
}
.promo-slot {
min-height: 250px; /* блок, который скрипт заполнит позже */
}
INP: ответ до работы
Обработчик с работой на 300 мс: без этого приёма клик ждал ответа 304 мс, с ним — 16 мс.
// Дать браузеру отрисовать реакцию до тяжёлой работы —
// клик сразу получает видимый ответ, а именно его и измеряет INP
const afterPaint = () =>
new Promise((resolve) => requestAnimationFrame(() => setTimeout(resolve, 0)));
button.addEventListener('click', async () => {
button.classList.add('is-loading'); // отрисуется сразу
await afterPaint();
const items = filterCatalogue(); // тяжёлая часть — уже после отрисовки
render(items);
button.classList.remove('is-loading');
});
Частые ошибки с Core Web Vitals
-
Гнаться за 100 в Lighthouse
Поиск берёт полевые данные; идеальная лабораторная оценка при плохих полевых ничего не меняет.
-
Проверять на быстром компьютере
Большинство визитов — со средних телефонов в мобильной сети.
-
Ленивая загрузка всего подряд
loading="lazy"на картинке первого экрана откладывает LCP. -
Проверять только главную
Карточки товаров и статьи приносят большую часть трафика и обычно страдают сильнее.
-
Скрипты всех сервисов подряд
Чаты, пиксели и виджеты складываются и портят INP сильнее собственного кода.
-
Ждать результата назавтра
Полевые данные догоняют за 28 дней — собственный замер показывает эффект сразу.
7 правил хороших Core Web Vitals
-
01
Бюджет до дизайна
Целевые цифры согласуются до первого макета — тогда дизайн с ними не спорит.
-
02
HTML с сервера
Главное содержимое приходит в первом ответе, а не после скриптов.
-
03
Одна приоритетная картинка
fetchpriority="high"— только на картинке первого экрана,loading="lazy"— на остальных. -
04
Свои шрифты
woff2 только с нужными символами, со своего сервера.
-
05
Размеры для всего, что грузится
Картинки, видео, iframe и виджеты получают место до того, как придут.
-
06
Сторонние скрипты по списку
Каждый обоснован и грузится после главного содержимого.
-
07
Свой замер в рабочем проекте
web-vitals присылает цифры настоящих посетителей — проблемы видны раньше отчётов.
Вопросы о Core Web Vitals
Что такое Core Web Vitals?
Три метрики Google для реального опыта посетителя: LCP — загрузка, INP — отклик, CLS — устойчивость.
Влияют ли они на позиции в поиске?
Да, как часть удобства страницы, но соответствие содержимого запросу важнее; из равных страниц выигрывает более быстрая.
Что стало с FID?
В марте 2024 года его заменил INP: FID измерял только первый клик, INP — все.
Почему PageSpeed Insights каждый раз разный?
Лабораторная часть — один прогон с шумом сети и сервера; полевая часть вверху отчёта стабильна.
Где увидеть данные своего сайта?
В Search Console, в отчёте Core Web Vitals, и в PageSpeed Insights для конкретной страницы.
У сайта нет полевых данных. Почему?
CrUX показывает только сайты и страницы с достаточным числом визитов; пробел закрывает собственный замер через web-vitals.
Мешают ли CMS и конструкторы?
Часто да: темы, модули и блоки — от WordPress до 1С-Битрикс и Tilda — приносят скрипты и стили на каждую страницу, нужны они там или нет.
Форма
Ускорить
сайт
Вывожу Core Web Vitals в зелёную зону на реальных телефонах: картинки, шрифты, скрипты и сервер. На новых проектах бюджет метрик согласую до начала дизайна. Расскажите о сайте — отвечу в течение рабочего дня.