Чому LCP — найпроблемніша метрика Core Web Vitals
Давайте чесно: серед трьох основних метрик Core Web Vitals — LCP, INP та CLS — саме Largest Contentful Paint (LCP) залишається тим самим каменем спотикання, об який запинається більшість сайтів. За даними HTTP Archive Web Almanac 2025, лише 62% мобільних сторінок у світі досягають порогу «добре» (менше 2,5 секунди). Тобто майже 4 з 10 сторінок завантажують основний контент занадто повільно. Це дуже багато.
А тепер до грошей. Сайти з хорошими показниками Core Web Vitals мають на 24% нижчий bounce rate, а інтернет-магазини фіксують зростання конверсій на 15–30% після оптимізації швидкості. Google використовує LCP як сигнал ранжування — повільні сторінки просто втрачають позиції. Без варіантів.
У цьому гіді ми розберемо LCP на складові (субчастини), знайдемо конкретні вузькі місця і застосуємо сучасні техніки — від fetchpriority до Speculation Rules API. Кожна секція містить робочий код, який можна впровадити вже сьогодні.
Що таке LCP і як він вимірюється
Визначення метрики
LCP вимірює час від початку навігації до моменту, коли найбільший видимий елемент у viewport повністю відрендерений. Це може бути зображення (<img>), poster-кадр відео (<video>), елемент із фоновим зображенням через url() або просто блок тексту.
І ось що цікаво: 73% мобільних LCP-елементів — це зображення. Тож якщо ви оптимізуєте тільки одну річ — оптимізуйте зображення.
Порогові значення
- Добре: менше 2,5 секунди — користувач сприймає сторінку як швидку
- Потребує покращення: 2,5–4 секунди — вже помітні затримки
- Погано: понад 4 секунди — користувач, ймовірно, просто піде
Чотири субчастини LCP
Google рекомендує розбивати LCP на чотири послідовні фази. Це важливо, бо кожна фаза вимагає принципово різного підходу до оптимізації — не можна лікувати все однією пігулкою:
- Time to First Byte (TTFB) — час відповіді сервера: від DNS-запиту до отримання першого байта HTML
- Resource Load Delay — затримка виявлення: скільки часу минає після TTFB, перш ніж браузер взагалі почне завантажувати LCP-ресурс
- Resource Load Duration — тривалість завантаження самого LCP-ресурсу (зазвичай зображення)
- Render Delay — затримка рендерингу: час від завершення завантаження до появи на екрані
В ідеалі приблизно 80% часу LCP припадає на мережеві запити (TTFB + завантаження ресурсу), і лише 20% — на затримки. Google рекомендує, щоб Resource Load Delay становив менше 10% від загального LCP.
Діагностика проблем із LCP
Chrome DevTools: панель Performance
Найшвидший спосіб почати — відкрити DevTools (F12), перейти на вкладку Performance, увімкнути «Web Vitals» і записати трейс при завантаженні. DevTools позначить LCP-елемент і покаже розбивку на субчастини. Ви одразу побачите, де саме «залипає».
Бібліотека web-vitals з атрибуцією
Для збору реальних польових даних (RUM) — а саме вони мають найбільше значення — використовуйте бібліотеку web-vitals з модулем атрибуції:
import { onLCP } from 'web-vitals/attribution';
onLCP((metric) => {
const { value, attribution } = metric;
const {
element,
url,
timeToFirstByte,
resourceLoadDelay,
resourceLoadDuration,
renderDelay
} = attribution;
console.group(`LCP: ${value.toFixed(0)}ms (${metric.rating})`);
console.log(`Елемент: ${element}`);
console.log(`URL ресурсу: ${url}`);
console.log(`TTFB: ${timeToFirstByte.toFixed(0)}ms`);
console.log(`Resource Load Delay: ${resourceLoadDelay.toFixed(0)}ms`);
console.log(`Resource Load Duration: ${resourceLoadDuration.toFixed(0)}ms`);
console.log(`Render Delay: ${renderDelay.toFixed(0)}ms`);
console.groupEnd();
// Відправте дані в аналітику
sendToAnalytics({
metric: 'LCP',
value,
rating: metric.rating,
ttfb: timeToFirstByte,
loadDelay: resourceLoadDelay,
loadDuration: resourceLoadDuration,
renderDelay: renderDelay
});
});
PageSpeed Insights і CrUX
PageSpeed Insights бере дані з Chrome User Experience Report (CrUX) — це реальні польові дані від користувачів Chrome за останні 28 днів. Для SEO саме ці дані найважливіші, бо Google їх використовує для ранжування. Lighthouse-аудит у тому ж PageSpeed Insights покаже конкретний LCP-елемент і запропонує рекомендації.
Оптимізація TTFB: фундамент швидкого LCP
Ось факт, який мене свого часу вразив: половина сайтів із поганим LCP має p75 TTFB понад 2270 мілісекунд. Це означає, що лише сама відповідь сервера вже перевищує поріг «добре» у 2500 мс. Якщо сервер відповідає повільно — жодна інша оптимізація не врятує.
Серверне кешування
Найефективніший спосіб зменшити TTFB — кешувати повністю згенерований HTML. Серверні кеші (Varnish, LiteSpeed Cache) перехоплюють запити до запуску PHP чи Node.js і повертають готовий HTML прямо з пам'яті:
# Nginx — кешування FastCGI для динамічних сайтів
fastcgi_cache_path /var/cache/nginx levels=1:2
keys_zone=SITE_CACHE:100m inactive=60m max_size=1g;
server {
location ~ \.php$ {
fastcgi_cache SITE_CACHE;
fastcgi_cache_valid 200 30m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
}
CDN і Edge Computing
CDN кешує контент на серверах, географічно близьких до користувачів. Повне кешування сторінок на Edge (Cloudflare, Fastly, Vercel Edge) може знизити TTFB до менше 50 мс. Це, до речі, зменшує навантаження на origin-сервер на 90–99%.
Налаштуйте правильні заголовки кешування:
# Кешування статичних ресурсів на 1 рік
Cache-Control: public, max-age=31536000, immutable
# Кешування HTML із stale-while-revalidate
Cache-Control: public, max-age=300, stale-while-revalidate=86400
Мінімізація редиректів
Кожен HTTP-редирект — це повний мережевий round-trip. Я бачив випадки, коли рекламне посилання проходило через скорочувач URL → HTTP → HTTPS → www → без www → фінальна сторінка. Чотири редиректи — це додаткові 400–800 мс просто в нікуди. Мінімізуйте ланцюжки до мінімуму.
Зменшення Resource Load Delay: ранне виявлення вирішує все
Resource Load Delay — це час між отриманням HTML і початком завантаження LCP-ресурсу. Медіанний сайт із поганим LCP витрачає на цю затримку 1,3 секунди — більше половини всього бюджету в 2,5 секунди! Це, мабуть, найбільш недооцінена субчастина, і водночас та, де найлегше отримати результат.
fetchpriority="high" — найпростіша і найефективніша оптимізація
За замовчуванням браузер присвоює зображенням низький пріоритет і підвищує його лише після завершення layout. Атрибут fetchpriority="high" обходить цей процес і каже браузеру: «Це важливо, качай зараз»:
<!-- LCP-зображення — завжди fetchpriority="high" -->
<img
src="/images/hero.avif"
alt="Головне зображення"
width="1200"
height="600"
fetchpriority="high"
>
<!-- Некритичні зображення — знижуємо пріоритет -->
<img
src="/images/sidebar-ad.webp"
alt="Реклама"
loading="lazy"
fetchpriority="low"
>
Наскільки це працює на практиці? Команда Google Flights додала fetchpriority="high" до hero-зображення і отримала покращення LCP на 700 мілісекунд. Etsy зафіксувала покращення на 4%, а деякі сайти бачать результати в 20–30% у лабораторних тестах. Один атрибут — і такий ефект.
Preload для ресурсів із пізнім виявленням
Якщо LCP-зображення — не прямий <img> в HTML (скажімо, це CSS background-image), браузер не знайде його, поки не завантажить і не розпарсить CSS. Preload вирішує саме цю проблему:
<head>
<!-- Preload + fetchpriority для CSS background-image -->
<link
rel="preload"
as="image"
href="/images/hero-bg.avif"
fetchpriority="high"
type="image/avif"
>
<!-- Preload для responsive зображень -->
<link
rel="preload"
as="image"
href="/images/hero-mobile.avif"
imagesrcset="/images/hero-mobile.avif 640w,
/images/hero-tablet.avif 1024w,
/images/hero-desktop.avif 1920w"
imagesizes="100vw"
fetchpriority="high"
>
</head>
Важливий момент: preload впливає на коли ресурс виявляється, а fetchpriority — на його пріоритет у черзі. Для максимального ефекту використовуйте обидва разом.
Preconnect для крос-доменних ресурсів
Якщо LCP-зображення живе на CDN або сторонньому домені, браузер витрачає час на DNS + TCP + TLS handshake. Preconnect дозволяє виконати це наперед:
<head>
<!-- Preconnect до CDN із зображеннями -->
<link rel="preconnect" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
</head>
Уникайте клієнтського рендерингу для LCP-контенту
Клієнтський рендеринг (CSR) — один із найгірших ворогів Resource Load Delay. Коли LCP-елемент генерується JavaScript-ом, браузер навіть не знає про ресурс, поки не завантажить і не виконає всі скрипти. Рішення — Server-Side Rendering (SSR) або Static Site Generation (SSG), щоб LCP-зображення було доступне вже у першому HTML.
Оптимізація Resource Load Duration: менше байтів — швидше
Сучасні формати: AVIF → WebP → JPEG
У 2026 році золоте правило форматів: AVIF першим, WebP другим, JPEG як fallback. AVIF забезпечує стиснення до 50% менше за JPEG при кращій якості, а WebP — на 25–34% менше. Підтримка браузерами вже давно не проблема: WebP — понад 97%, AVIF — теж чудова і продовжує зростати.
<!-- Елемент picture з fallback-ланцюжком -->
<picture>
<source
srcset="/images/hero.avif"
type="image/avif"
>
<source
srcset="/images/hero.webp"
type="image/webp"
>
<img
src="/images/hero.jpg"
alt="Головне зображення сторінки"
width="1200"
height="600"
fetchpriority="high"
>
</picture>
Responsive images із srcset
Мобільний користувач не повинен завантажувати десктопне зображення 1920×1080 — це марнотратство трафіку. Використовуйте srcset і sizes для автоматичного вибору потрібного розміру:
<img
srcset="/images/hero-640.avif 640w,
/images/hero-1024.avif 1024w,
/images/hero-1920.avif 1920w"
sizes="(max-width: 640px) 100vw,
(max-width: 1024px) 80vw,
1200px"
src="/images/hero-1024.avif"
alt="Головне зображення"
width="1200"
height="600"
fetchpriority="high"
>
Стиснення на стороні CDN
Більшість сучасних CDN (Cloudflare, imgix, Cloudinary) вміють автоматично конвертувати зображення в AVIF/WebP, змінювати розмір і стискати на льоту. Увімкніть auto-format на CDN — і можна забути про ручну конвертацію кількох форматів та розмірів. Серйозно, це дуже спрощує життя.
Зменшення Render Delay: останній крок до відображення
Render Delay — це час між завершенням завантаження LCP-ресурсу і його фактичним відображенням на екрані. Звідки він береться? Рендер-блокуючі ресурси: CSS, шрифти та синхронний JavaScript.
Критичний CSS (Critical CSS)
Виокремте CSS, необхідний для першого екрана, і вставте його inline прямо у <head>. Решту CSS завантажте асинхронно:
<head>
<!-- Критичний CSS inline -->
<style>
/* Тільки стилі для above-the-fold контенту */
.hero { position: relative; width: 100%; }
.hero img { width: 100%; height: auto; display: block; }
.nav { display: flex; align-items: center; }
</style>
<!-- Решта CSS — асинхронно -->
<link
rel="preload"
href="/css/main.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
>
<noscript>
<link rel="stylesheet" href="/css/main.css">
</noscript>
</head>
Оптимізація завантаження шрифтів
Кастомні шрифти можуть блокувати рендеринг тексту (а текст іноді і є LCP-елементом). Використовуйте font-display: swap, щоб браузер одразу показав текст системним шрифтом, поки кастомний підвантажується:
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}
/* Preload шрифту в <head> */
/* <link rel="preload" href="/fonts/custom.woff2"
as="font" type="font/woff2" crossorigin> */
Усуньте рендер-блокуючий JavaScript
Скрипти без defer чи async блокують парсинг HTML і, як наслідок, рендеринг LCP. Додайте defer до всіх некритичних скриптів — це елементарна зміна, яка часто дає помітний результат:
<!-- Блокує рендеринг — ПОГАНО -->
<script src="/js/analytics.js"></script>
<!-- Не блокує рендеринг — ДОБРЕ -->
<script src="/js/analytics.js" defer></script>
Speculation Rules API: миттєві переходи між сторінками
А тепер про цікаве. Speculation Rules API дозволяє браузеру попередньо завантажити (prefetch) або навіть повністю відрендерити (prerender) сторінки, на які користувач, ймовірно, перейде. Результат — практично миттєва навігація з LCP, що наближається до нуля.
<script type="speculationrules">
{
"prerender": [
{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": { "href_matches": "/logout" } },
{ "not": { "href_matches": "/api/*" } }
]
},
"eagerness": "moderate"
}
],
"prefetch": [
{
"where": { "href_matches": "/*" },
"eagerness": "conservative"
}
]
}
</script>
Параметр eagerness контролює агресивність:
- conservative — prefetch/prerender тільки при кліку (мінімальне витрачання ресурсів)
- moderate — при наведенні курсору на посилання (золота середина)
- eager — негайно для всіх визначених URL (максимальна швидкість, але більше витрат пам'яті)
Є нюанс: у 2026 році Speculation Rules API підтримується лише в Chromium-браузерах (Chrome, Edge, Opera). Для Firefox і Safari доведеться використовувати класичний <link rel="prefetch"> як fallback.
Типові помилки, які вбивають LCP
1. Lazy loading LCP-зображення
Це, чесно кажучи, помилка номер один. 16% мобільних сайтів помилково застосовують loading="lazy" до LCP-зображення. Ірониія в тому, що lazy loading відкладає завантаження, поки елемент не наблизиться до viewport — але LCP-зображення вже у viewport! Результат: затримка на сотні мілісекунд. Правило просте — ніколи не додавайте loading="lazy" до зображень першого екрана.
2. Клієнтський рендеринг без SSR
SPA-фреймворки (React, Vue, Angular) за замовчуванням рендерять контент на клієнті. Браузер отримує практично порожній HTML, завантажує JavaScript-бандл, виконує його, і тільки тоді вставляє LCP-елемент у DOM. Це може додавати 1–3 секунди до LCP. Вихід — SSR (Next.js, Nuxt, Angular Universal) або SSG.
3. Ланцюжки завантаження (request chains)
LCP-зображення, яке підвантажується через CSS background-image у файлі, підключеному через @import в іншому CSS — це класичний ланцюжок залежностей. Браузер навіть не дізнається про зображення, поки послідовно не обробить два CSS-файли. Завжди розміщуйте LCP-зображення безпосередньо в HTML.
4. Занадто великий HTML-документ
Якщо тег <img> LCP-зображення розташований далеко в HTML і не потрапляє в перші 10 КБ, браузеру знадобляться додаткові round-trip для його виявлення. Розміщуйте LCP-елемент якомога раніше в розмітці.
5. Відсутність явних розмірів зображення
Зображення без атрибутів width і height змушують браузер виконувати додатковий layout після завантаження. Це погіршує і CLS, і Render Delay LCP одночасно. Завжди вказуйте розміри — це справді елементарна річ.
Чекліст оптимізації LCP
Отже, фінальна таблиця пріоритетів. Рекомендую йти саме в такому порядку:
- Перевірте TTFB — чи не перевищує він 800 мс? Якщо так — це пріоритет номер один
- Додайте
fetchpriority="high"до LCP-зображення — найпростіший і найефективніший крок - Видаліть
loading="lazy"з LCP-зображення, якщо воно є - Переконайтесь, що LCP-зображення є в HTML — не в CSS background, не генерується JavaScript-ом
- Preload + preconnect для крос-доменних LCP-ресурсів
- Конвертуйте в AVIF/WebP і використовуйте responsive images
- Вбудуйте критичний CSS і defer-іть решту
- Додайте Speculation Rules для миттєвих переходів між сторінками
- Моніторте польові дані через web-vitals і CrUX
Часті запитання (FAQ)
Що вважається хорошим показником LCP?
Google рекомендує LCP менше 2,5 секунди на 75-му перцентилі. Це означає, що 75% ваших відвідувачів повинні бачити основний контент протягом 2,5 секунди. Від 2,5 до 4 секунд — потребує покращення, понад 4 секунди — вже погано.
Чим відрізняється fetchpriority від preload?
preload впливає на час виявлення ресурсу — він повідомляє браузеру про існування ресурсу раніше, ніж той знайде його сам. fetchpriority впливає на пріоритет у черзі завантаження — наскільки важливий цей ресурс порівняно з іншими. Для LCP-зображень найкраще використовувати обидва разом — вони доповнюють одне одного.
Чи впливає LCP на SEO-ранжування?
Так, і це не просто теорія. Google використовує Core Web Vitals, включаючи LCP, як сигнал ранжування. Сторінки на першій позиції на 10% частіше мають хороші показники CWV порівняно зі сторінками на дев'ятій позиції. А у 2026 році, коли AI-генерований контент став масовим явищем, технічна якість сайту — ще важливіший фактор диференціації.
Який формат зображень найкращий для LCP у 2026 році?
Рекомендований пріоритет: AVIF → WebP → JPEG. AVIF дає найкраще стиснення (до 50% менше за JPEG) з підтримкою HDR. WebP — надійний fallback із підтримкою понад 97% браузерів. Використовуйте елемент <picture> з кількома <source>, і браузер сам обере оптимальний формат.
Чи можна оптимізувати LCP для SPA (React, Vue)?
Можна, але це складніше. SPA за замовчуванням використовують клієнтський рендеринг, і це суттєво збільшує Resource Load Delay. Найкращий шлях — перейти на SSR або SSG (Next.js для React, Nuxt для Vue). Сервер віддає готовий HTML із LCP-елементом, і браузер може почати завантаження одразу — без очікування JavaScript.