Веб-производительность

LCP: как оптимизировать Largest Contentful Paint

LCP оптимизация: как улучшить Largest Contentful Paint для Core Web Vitals

LCP — главный показатель скорости загрузки в [Core Web Vitals](/glossary/core-web-vitals). Он измеряет, как быстро пользователь видит основной контент страницы. Разбираем: что влияет на LCP, почему он тормозит, и как довести его до зелёного порога в реальных проектах.

Largest Contentful Paint (LCP) — метрика Core Web Vitals, которая с 2021 года влияет на ранжирование в Google. Это не просто технический показатель: он отражает реальное восприятие загрузки страницы пользователем. Плохой LCP — это когда посетитель видит пустой экран или незагруженную шапку и уходит, не дождавшись контента.

Таймлайн загрузки: LCP фиксируется в момент отрисовки самого крупного элемента в видимой области. Цель — попасть в зелёную зону до 2,5 секунд.
По данным Google, улучшение LCP с «плохого» до «хорошего» снижает показатель отказов в среднем на 24%. На e-commerce это напрямую влияет на конверсию.

Что такое LCP и зачем его оптимизировать

LCP измеряет время от начала навигации до момента, когда наибольший по площади контентный элемент (текст или изображение) становится видимым в области просмотра (viewport). Это пороговое значение, за которым Google считает загрузку «завершённой» с точки зрения пользовательского опыта.

В отличие от FCP (First Contentful Paint), который фиксирует момент появления первого пикселя, LCP отслеживает именно значимый контент. Страница может показать спиннер через 0.3 сек, но если главное изображение появится через 5 сек — LCP будет 5 сек.

< 2.5 сек

Хороший LCP

Зелёный порог Google. Цель для большинства страниц

2.5–4 сек

Требует улучшения

Жёлтая зона — LCP заметен пользователю, нужна оптимизация

> 4 сек

Плохой LCP

Красная зона — значительный ущерб для UX и ранжирования

75%

Порог CrUX

Google оценивает LCP сайта по 75-му перцентилю реальных пользователей

Google использует данные Chrome User Experience Report (CrUX) — реальные замеры у реальных пользователей Chrome. Ваш PageSpeed Insights может показывать «зелёный», а CrUX — «жёлтый». Ориентируйтесь на CrUX: именно по нему Google принимает решение о ранжировании.

Какие элементы браузер считает LCP-кандидатами

Браузер не отслеживает любой элемент страницы — он смотрит только на конкретные типы и выбирает наибольший по площади в viewport на момент завершения загрузки.

<img> элементы
Стандартные изображения. Самый частый LCP-кандидат на большинстве страниц. Время = момент появления декодированного изображения в viewport.
<image> в SVG
Изображения внутри SVG-элементов. Обрабатываются как обычные img с точки зрения LCP.
CSS background-image
Фоновые изображения через CSS. Важный нюанс: браузер не начинает загружать background-image до тех пор, пока не построит CSSOM. Это один из главных источников задержки LCP.
Блоки с текстом
Элементы <p>, <h1>–<h6>, <div> и другие с текстовым содержимым. Если текстовый блок крупнее изображения — именно он становится LCP.
<video> с poster
Постер видеоэлемента (атрибут poster). Если видео занимает большую часть экрана, poster должен загружаться максимально быстро.
Элементы внутри <iframe>, а также элементы без визуального размера (display: none, visibility: hidden, opacity: 0) не учитываются как LCP. Если ваш hero-баннер скрыт до JS-инициализации — LCP может фиксироваться на совершенно другом элементе.

Из чего складывается время LCP

Google разбивает LCP на 4 подкомпоненты. Понимание каждого из них — ключ к правильной диагностике и приоритизации оптимизаций.

КомпонентЧто измеряетТипичная доля
TTFB (Time to First Byte)Время до получения первого байта HTML от сервера10–40%
Resource Load DelayЗадержка между TTFB и началом загрузки LCP-ресурса10–30%
Resource Load DurationВремя загрузки самого LCP-ресурса (изображения, шрифта)30–60%
Element Render DelayЗадержка между загрузкой ресурса и его появлением в viewport0–20%

Правило: атакуйте компонент с наибольшей долей. Если TTFB занимает 3 из 5 секунд LCP — оптимизация изображений даст минимальный эффект. Сначала нужно улучшить серверный ответ.

Главные причины медленного LCP

90% плохих LCP объясняются одними и теми же причинами. Диагностика занимает 15 минут в DevTools или PageSpeed Insights.

Медленный TTFB

Сервер отвечает дольше 600 мс. Причины: нет кэширования, слабый хостинг, тяжёлые запросы к БД, отсутствие CDN. При TTFB > 800 мс достичь LCP < 2.5 сек почти невозможно без прочих оптимизаций.

Неоптимизированные изображения

LCP-изображение весит 500 KB+ в JPEG вместо 80 KB в WebP/AVIF. Нет атрибута fetchpriority="high", нет preload. Браузер обнаруживает изображение поздно и загружает медленно.

Render-blocking ресурсы

CSS и JS в <head> без async/defer блокируют рендеринг. Пока браузер не загрузит и не выполнит их — LCP-элемент не появится. Каждый лишний скрипт в head добавляет задержку.

Медленная загрузка шрифтов

Если LCP — текстовый блок, а шрифт загружается 2+ сек, браузер показывает FOIT (невидимый текст) или FOUT (системный шрифт). Время до появления правильного текста = LCP.

Lazy load на LCP-элементе

Атрибут loading="lazy" на главном изображении hero-секции — одна из самых частых ошибок. Браузер намеренно откладывает загрузку, а это прямой удар по LCP.

LCP в клиентском рендеринге

В SPA (React, Vue, Angular) контент генерируется в браузере через JavaScript. Браузер видит пустой HTML → загружает JS → рендерит контент. Весь этот процесс суммируется в LCP.

Как оптимизировать LCP: пошаговый план

Оптимизация LCP — это не один трюк, а набор взаимосвязанных улучшений. Работайте последовательно от самых высокодоходных.

Шаг 1: Снизить TTFB до 200–400 мс

TTFB — фундамент. Если сервер отвечает медленно, все остальные оптимизации работают «поверх» этого потолка.

  1. Настройте HTTP-кэширование: Cache-Control: max-age=31536000 для статики, s-maxage для CDN-прокси.
  2. Включите сжатие: Brotli (приоритет) или gzip для HTML, CSS, JS. Brotli даёт на 15–25% меньший размер, чем gzip.
  3. Подключите CDN: Cloudflare, Fastly, BunnyCDN. Для статичных сайтов — edge caching снижает TTFB до 20–50 мс.
  4. Оптимизируйте базу данных: индексы на часто используемых полях, кэш запросов через Redis/Memcached.
  5. Используйте HTTP/2 или HTTP/3: множественные запросы по одному соединению без head-of-line blocking.
Цель по TTFB: < 200 мс для сервера + CDN. Если у вас Nginx + статический HTML + CDN — это реально. Если PHP/Node без кэша и запросы к БД — нужна оптимизация на уровне приложения.

Шаг 2: Оптимизировать LCP-изображение

Если LCP-элемент — изображение (hero, product image), это дерево оптимизаций с высоким ROI.

  • Конвертируйте в современные форматы: WebP (экономия 25–35% vs JPEG) или AVIF (40–55% vs JPEG). Используйте <picture> с fallback.
  • Добавьте атрибут fetchpriority="high" на LCP-изображение — браузер загрузит его в первую очередь.
  • Уберите loading="lazy" с LCP-элемента. Lazy load уместен только для изображений ниже first viewport.
  • Добавьте <link rel="preload" as="image"> в <head> для LCP-изображения — браузер начнёт загрузку до парсинга body.
  • Укажите атрибуты width и height для предотвращения CLS. Браузер зарезервирует место до загрузки изображения.
  • Настройте srcset и sizes для адаптивной загрузки: мобиль получит изображение 400 px вместо 1600 px.
Комбинация fetchpriority="high" + preload + WebP/AVIF + правильный srcset даёт в среднем 1–2 секунды улучшения LCP на реальных e-commerce проектах.

Шаг 3: Устранить render-blocking ресурсы

Каждый ресурс, который блокирует рендеринг, добавляет задержку к LCP. Цель — ни одного блокирующего ресурса в критическом пути.

Тип ресурсаПроблемаРешение
JavaScript в <head>Браузер останавливает парсинг HTML и выполняет скриптdefer или async на всех не-критических скриптах
CSS в <head>Браузер не рендерит ничего до загрузки всего CSSCritical CSS inline + async loadCSS для некритичного
Сторонние скриптыАналитика, чат-боты, пиксели загружаются в headПеренести в body или загружать с задержкой (setTimeout 3000)
Шрифты без preloadБраузер обнаруживает шрифт только после парсинга CSS<link rel="preload" as="font"> + font-display: swap

Шаг 4: Оптимизировать шрифты (если LCP — текст)

Когда LCP-элемент — текстовый блок (заголовок, лид), проблема может быть в задержке отрисовки шрифта.

  1. Добавьте font-display: swap или optional в @font-face. Браузер покажет системный шрифт немедленно и заменит на кастомный после загрузки.
  2. Используйте <link rel="preload" as="font" type="font/woff2" crossorigin> для критичных шрифтов в <head>.
  3. Ограничьте набор символов: используйте subsetting для загрузки только нужных символов (латиница, кириллица).
  4. Self-host шрифты вместо загрузки с Google Fonts — убираете дополнительный DNS-lookup и соединение.
  5. Настройте size-adjust, ascent-override, descent-override в @font-face для уменьшения CLS при подмене шрифта.

Шаг 5: SSR/SSG для JavaScript-фреймворков

Если сайт на React, Vue или Next.js без SSR — LCP будет высоким по умолчанию: браузер должен загрузить, выполнить JavaScript и только потом отрендерить контент.

Server-Side Rendering (SSR)
HTML генерируется на сервере при каждом запросе. Браузер получает готовый HTML, парсит его и LCP-элемент появляется без ожидания JS. Лучший вариант для динамического контента.
Static Site Generation (SSG)
HTML генерируется на этапе сборки. Сервер отдаёт готовый файл — максимально быстрый TTFB и LCP. Идеал для блогов, лендингов, страниц без персонализации.
Incremental Static Regeneration (ISR)
SSG с периодической регенерацией (Next.js). Сочетает скорость статики с актуальностью данных. Оптимален для большинства CMS-контента.
Streaming SSR
Сервер начинает отправлять HTML до завершения рендеринга — браузер прогрессивно отображает контент. React 18 + Next.js 13+ поддерживают out of the box.
Partial Hydration и Islands Architecture (Astro, Qwik) — ещё более эффективный подход: гидрируются только интерактивные компоненты, статичный контент рендерится мгновенно. Для контентных сайтов это 0.5–1 сек выигрыша LCP.

Шаг 6: CSS background-image как LCP

Если LCP-элемент использует background-image через CSS — браузер не начнёт его загрузку до построения CSSOM. Это одна из самых коварных причин медленного LCP.

  • Замените CSS background-image на <img> с fetchpriority="high" — браузер обнаружит его на этапе HTML-парсинга.
  • Если замена невозможна — используйте <link rel="preload" as="image"> для ручного запуска загрузки.
  • Для адаптивных фонов используйте imagesrcset и imagesizes в preload-теге.
  • Переместите CSS, содержащий LCP background-image, в inline <style> — убирает один сетевой запрос.

Инструменты для измерения и диагностики LCP

Правильная диагностика важнее оптимизации вслепую. Используйте оба типа инструментов: Lab (синтетические тесты) и Field (реальные пользователи).

ИнструментТип данныхЧто даётКогда использовать
PageSpeed InsightsLab + Field (CrUX)Оценка LCP, разбивка по подкомпонентам, конкретные рекомендацииПервичный аудит, проверка изменений
Chrome DevTools PerformanceLabWaterfall загрузки, точная причина задержки LCP, flame chartГлубокая диагностика конкретной проблемы
Lighthouse CILabАвтоматизированные проверки в CI/CD, история LCP по релизамРегрессионный контроль
WebPageTestLabТест из разных регионов, видео сравнение, filmstrip, waterfallПроверка CDN, регионального LCP
Google Search Console (CWV)Field (CrUX)Реальный LCP по группам URL, URL с проблемамиМониторинг в продакшне
web-vitals.jsFieldJavaScript API для сбора LCP у реальных пользователей в свою аналитикуCustom мониторинг, RUM

Как диагностировать LCP в Chrome DevTools

DevTools — самый точный инструмент для понимания, что именно тормозит LCP на конкретной странице.

  1. Откройте DevTools → Performance → нажмите Record, перезагрузите страницу, остановите запись.
  2. В Timings найдите маркер LCP — он показывает точное время и элемент.
  3. Изучите Waterfall: найдите ресурс LCP-элемента и проверьте, когда началась его загрузка относительно TTFB.
  4. Обратите внимание на красные полосы — это render-blocking ресурсы. Они прямо перед LCP.
  5. Вкладка Network → Filter по типу Image — найдите LCP-изображение, проверьте приоритет (должен быть High).
  6. Coverage вкладка — показывает неиспользуемый CSS/JS. Большой объём неиспользуемого кода = задержка LCP.
В DevTools Network для LCP-изображения должно быть: Priority: High, Initiator: Preload или Parser (не скрипт). Если Initiator — скрипт или XHR — значит изображение обнаруживается поздно.

Частые вопросы

PageSpeed Insights показывает как лабораторные данные (Lighthouse), так и полевые данные CrUX. Если зелёный — вероятно вы смотрите на Lighthouse. CrUX в PSI и Search Console — это реальные пользователи Chrome. У них может быть медленное соединение, старые устройства, другая геолокация. Ориентируйтесь на CrUX/Field данные — именно их Google использует для ранжирования.
Частично — да. Подключение CDN, настройка HTTP-кэширования, включение Brotli-сжатия — это конфигурация сервера. Конвертация изображений в WebP/AVIF и их сжатие — тоже без правки кода на сайте. Но fetchpriority, preload, устранение lazy load с hero и SSR — требуют работы с кодом.
Фокусируйтесь на шрифтах и TTFB. Добавьте preload для веб-шрифта, font-display: swap, самохостите шрифты. Если текст в большом блоке, у которого нет критичного CSS — убедитесь, что CSS, влияющий на этот блок, не блокирует рендеринг. Также проверьте TTFB: даже без изображения медленный сервер = высокий LCP.
Да. LCP входит в Core Web Vitals — сигнал Page Experience, который Google официально использует как фактор ранжирования с 2021 года. Плохой LCP не обрушит позиции мгновенно, но при прочих равных сайт с хорошим LCP будет иметь преимущество. Особенно заметно на мобильных устройствах.
Приоритизируйте страницы с высоким органическим трафиком и посадочные страницы для платного трафика. Google в Search Console показывает, какие URL имеют «Poor» LCP — начните с них. Главная, категории и карточки товаров в e-commerce — обычно первые кандидаты. Технические улучшения (шрифты, CDN, Brotli) применяются глобально.