В статье:
-
Что такое LCP — показатель Largest Contentful Paint
-
Как измерить LCP: инструменты веб-мастера
-
Как улучшить показатель LCP:
-
Ускорить время ответа сервера
-
Решить блокировку рендеринга JavaScript и CSS
-
Ускорить загрузку ресурсов
-
Оптимизировать рендеринг на стороне клиента
-
В мае Google определил новый способ оценки пользовательского опыта. Показатель называется Google Core Vitals, он связан со скоростью загрузки сайта и появления на нем контента.
Google Core Vitals состоит из трех метрик:
- FID — First Input Delay — время между первым взаимодействием пользователя со страницей и ответом бразуера.
- CLS — Cumulative Layout Shift — показатель смещения элементов во время загрузки страницы.
- LCP — Largest Contentful Paint — определяет время, за которое браузер отрисовывает самый крупный видимый объект в области просмотра.
Про CLS у нас есть подробный материал «Как оптимизировать CLS: сдвиги макета страницы, которые мешают пользователям», в этой статье поговорим о показателе LCP и способах его улучшить.
Что такое LCP — показатель Largest Contentful Paint
Largest Contentful Paint — время рендеринга самого большого элемента, видимого в области просмотра пользователем — изображения, текстового блока, видео или другого контента. Учитываются те размеры элементов, которые видны пользователю. Если элемент частично скрыт за областью просмотра, эти невидимые части не берутся в расчет.
Самый аккуратный способ определить время отображения основного содержимого страницы — использовать API Largest Contentful Paint (LCP).
Как это происходит:
При загрузке страницы контент может меняться, поэтому каждый раз, когда появляется новый большой элемент, браузер отправляет PerformanceEntry c типом largest-contentful-paint. Когда пользователь начинает взаимодействовать со страницей, отправка метрики прекращается. Нужное значение — время самого последнего отправленного события.
Отрисовка самого большого элемента может происходить и до полной загрузки страницы. К примеру, логотип Instagram — самый большой элемент, он загружается относительно рано и остается самым большим элементом, пока постепенно отображается остальной контент.
В следующем примере самый большой элемент изменяется по мере загрузки содержимого — сначала им был текст, потом самым большим объектом стала картинка.
Инструменты, которые позволяют измерить показатель LCP:
- Отчет Core Web Vitals в Search Console, он находится в Отчете об основных интернет-показателях
- PageSpeed Insights
Проверка скорости сайта от PR-CY бесплатно анализирует загрузку страницы по ключевым параметрам, проверяет десктопное и мобильное отображение. Сервис дает рекомендации и прикидывает, сколько можно сэкономить, если их внедрить на сайте.
Какой показатель LCP считается хорошим
Нужно стремиться, чтобы отрисовка самого большого контента происходила не дольше, чем за 2,5 секунды после начала загрузки страницы. Тогда пользователям будет удобно работать на сайте.
Инструменты для измерения показывают сводный показатель LCP для 75 % посещений URL.
Как улучшить показатель LCP
На LCP влияют четыре фактора:
- время ответа сервера;
- JavaScript и CSS с блокировкой рендеринга;
- время загрузки ресурса;
- рендеринг на стороне клиента.
Рассмотрим эти факторы, сопутствующие им проблемы и способы оптимизировать показатели.
Медленный ответ сервера
Чем быстрее браузер получает контент с сервера, тем быстрее загрузка страницы и тем лучше показатель LCP.
Вы можете улучшить TTFB — время до первого байта. Какие есть способы:
- Обратитесь к рекомендациям по производительности сервера.
Многие веб-фреймворки, работающие на сервере, имеют такие рекомендации, нужные для ускорения. Как исправить перегруженный сервер - Используйте CDN (Content Delivery Network).
CDN хранят контент и быстро отдают его клиентам из разных географических точек. Подробнее есть в нашей статье. По выводам из исследования, использование CDN коррелировало с улучшением показателей скорости загрузки TTFB, особенно на десктопах. - Кэшируйте страницы.
Статичный HTML, который редко изменяется, можно закэшировать в браузере пользователя, чтобы при каждом визите не загружать контент заново. О кэшировании, сжатии gzip и brotli и других способах оптимизации есть отдельный материал. - Попробуйте сервис-воркеры
Service Worker могут перехватывать запросы с сервера и управлять кэшем — например, кэшировать только часть страницы или обновлять кэш только при изменении содержимого. - Устанавливайте сторонние подключения на раннем этапе.
На LCP могут влиять запросы сервера к сторонним источникам. Можно дать сигнал браузеру, что страница как можно скорее собирается установить соединение, для этого есть rel=» preconnect «.
<link rel="preconnect" href="https://site.ru>
Другой вариант — dns-prefetch для ускорения поиска DNS, подходит для браузеров, которые не поддерживают preconnect.
<link rel="dns-prefetch" href="https://site.ru">
Можно использовать оба варианта для разных браузеров.
<link rel="preconnect" href="https://site.ru">
<link rel="dns-prefetch" href="https://site.ru">
Блокировка рендеринга JavaScript и CSS
Браузер преобразовывает разметку HTML в дерево DOM, а потом уже отображает контент. Он не сможет продолжать работу, если обнаружит ресурсы, блокирующие рендеринг: внешние таблицы стилей link rel=»stylesheet» и сценарии JavaScript script src=»main.js». Чтобы ускорить загрузку содержимого страницы, нужно отложить все некритические JavaScript и CSS.
Неиспользуемый JavaScript и CSS можно найти с помощью Chrome DevTools на вкладке Coverage.
Найденный неиспользуемый CSS можно вообще удалить или переместить в другую таблицу стилей, если он нужен на других страницах сайта.
Если CSS не нужен для начального рендеринга, можно использовать loadCSS для асинхронной загрузки файлов, который использует rel=»preload» и onload.
<link rel="preload" href="stylesheet.css" as="style" onload="this.rel='stylesheet'">
Критический CSS можно включить в head, если он нужен для верхней части страницы. Встраивание стилей таким образом позволит не делать двусторонний запрос для получения критического CSS.
Как автоматизировать добавление встроенных стилей на сайт:
- Critical, CriticalCSS и Penthouse извлекают и встраивают верхний CSS;
- Critters встраивает критический CSS и загружает остальные в отложенном режиме.
Для JavaScript также можно использовать асинхронную загрузку.
Еще полезна минификация или минимизация кода CSS и JavaScript — удаление символов, которые не нужны браузеру для чтения кода. Минификаторы удаляют отступы, интервалы, разделители и комментарии, файл по сути не меняется, но становится легче.
Список бесплатных инструментов для минимизации CSS, JS, HTML-файлов есть в статье.
Долгая загрузка ресурсов
Время, которое требуется контенту для загрузки, влияет на LCP, так что имеет смысл поработать с элементами на странице.
Что можно сделать:
- Оптимизировать изображения.
Если на сайте много больших по размеру изображений, которые замедляют загрузку страниц, попробуйте lazy loading картинок — постепенную подгрузку, которая обычно зависит от действий пользователя на странице. Еще можно сжать изображения, если они много весят, попробовать новый формат WebP, обратиться к CDN. - Загрузить важное сначала
Критически важные ресурсы, например, шрифты, изображения или видеозаписи, нужно загрузить первым делом. Для придания ресурсу приоритета есть < link rel = «preload» >. - Использовать сервис-воркеры
В предыдущем пункте упоминали сервис-воркеры для выборочного кэширования, их можно использовать и для изображений и других элементов, которые редко обновляют на странице. - Использовать gzip или brotli
Эти виды сжатия могут значительно уменьшить размер файлов HTML, CSS и JavaScript при их передаче между сервером и браузером. Об настройке в статье «Как ускорить сайт с помощью gzip, brotli, минификации и других способов».
Рендеринг на стороне клиента
Есть сайты, которые работают через рендеринг на стороне клиента (CSR) — то есть рендеринг страниц происходит в браузере с использованием JavaScript, все обрабатывается на стороне клиента, а не на сервере.
Основной недостаток такого подхода в том, что по мере роста сайта, добавления новых библиотек и кода начинает страдать скорость загрузки и отображения контента для пользователя.
Что можно сделать:
- минифицировать код JavaScript — сократить и сжать файл;
- выявить неиспользуемые элементы JavaScript, удалить или отложить их;
- минимизировать неиспользуемые полифиллы, которые используют для работы сайта в старых браузерах. Сведите к минимуму неиспользуемые полифилы и ограничьте их использование средами, где они необходимы.
В некоторых случаях можно использовать предварительный рендеринг. В таком способе рендер выполняется в headless браузере типа Chrome, который генерирует статические файлы HTML, а их уже подставляют в ответ сервера.
Предварительный рендеринг не нагружает реальный сервер и позволяет улучшить показатель LCP, но не подходит для страниц с изменяемым или с введенным пользователем контентом.
Скорость загрузки ресурса на компьютере и мобильных устройствах можно проверить в Анализе сайта от PR-CY. Он проверяет сайт по 70+ параметрам, включая скорость загрузки и отображения контента, анализирует, что реализовано на сайте для ускорения, и дает советы, что еще можно улучшить.
Некоторые подробные тесты и графики, а также проверка внутренних страниц и отслеживание позиций доступны на платных тарифах. Но мы даем новым пользователям неделю на бесплатный тест сервиса — оставайтесь, если понравится!
Подключить
Подробнее о LCP в статьях «Largest Contentful Paint (LCP)» и «Optimize LCP».
В комментариях напишите, о чем еще вам было бы интересно почитать по теме оптимизации и работы с техническими характеристиками сайта.
Поисковые системы постоянно совершенствуют алгоритмы ранжирования, чтобы на верхних строчках выдачи попадали качественные сайты, которые обеспечивают идеальный пользовательский опыт. Юзеры должны найти ответ на свой вопрос, а не пробираться к нему через тонну рекламных объявлений.
Автоматизированные алгоритмы постоянно следят за тем, чтобы пользователи оставались довольны. Для этих целей придумали поведенческие факторы — метрики, позволяющие измерить качество user experience. Если контент просто заточен под ключи и не имеет ценности, ПФ это покажут.
Если хотите создавать инфосайты под контекстную рекламу или собираетесь монетизировать их партнёрками и рассчитываете на бесплатный трафик, придётся адаптировать проекты под новые алгоритмы. Сегодня Monstro расскажет об одном из ключевых факторов, который влияет на эффективность продвижения в любых нишах.
Что такое показатель Largest Contentful Paint (LCP)?
Конкуренция в поисковой выдаче постоянно растёт потому что появляется всё больше качественных сайтов. В 2021 году контента, раскрывающего пользовательский интент уже мало, чтобы находиться в ТОПе годами. Сайт должен быть быстрым, удобным и предлагать дополнительные инструменты, которых нет у других игроков ниши.
В плане совершенствования формулы ранжирования Google ушёл далеко вперед от Яндекса. Пока в Яндексе работают над нейросетями, которые генерируют контент, Гугл вводит в действие новые алгоритмы и делает всё, чтобы информационные и коммерческие проекты подстраивались под новую реальность.
Google анонсировал Core Web Vitals ещё в прошлом году, но отметил, что новый фактор ранжирования начнёт учитываться основным алгоритмом только в 2021 году. Развёртывание запланировали на май и отметили, что у вебмастеров ещё куча времени, чтобы пофиксить проблемы.
Подстраиваться под изменения или нет — каждый решает сам. Понятно, что новый алгоритм не поменяет выдачу в один момент, но изменения однозначно будут. Ещё больший сдвиг в сторону качества сайта говорит о том, что Google любит не только ссылки, а заботится об аудитории.
Если на проекте много рекламы, которая грузится по 10-15 секунд и перекрывает основной контент, в процессе измерения новых метрик это будет видно и сайт может потерять позиции. Такие проекты не должны попадать в ТОП и хорошо ранжироваться. Особенно если рядом есть чистые сайты с хорошим контентом и высокой скоростью загрузки.
В состав Core Web Vitals («Основных интернет-показателей») входят 3 метрики, каждая из которых отвечает за свои задачи. В совокупности они помогают оценить, насколько быстро сайт загружает контент и как скоро он становится доступен для пользователей. Если значения для метрик из CWV будут слишком маленькими, сайт может вылететь из ТОПа.
Одной из метрик является Largest Contentful Paint (LCP). Параметр измеряет скорость загрузки, а точнее момент, когда загружается основной контент на странице. К примеру, если в хедере стоит рекламный блок и он грузится 5-10 секунд, сайт не пройдет проверку по LCP.
Largest Contentful Paint отражает время, в течение которого на странице загружается самый тяжелый блок. Это может быть картинка, видео, содержание или что-то другое. Всё зависит от структуры шаблона и особенностей проекта.
Обычно у вебмастеров, которые далеки от технических терминов, возникают проблемы с пониманием сущности Core Web Vitals, хотя ничего сложного в этом нет. Основные интернет-показатели Google не придумали на пустом месте, метрики существовали давно.
Гугл просто объединил их в единую систему, а затем призвал вебмастеров провести комплексную оценку значения метрик и внести изменения в технические параметры, чтобы обеспечить более качественный пользовательский опыт. Те, кто не будут ничего менять, останутся за бортом.
Самый крупный элемент на странице одновременно является самым важным, поэтому вопросы как улучшить LCP уже давно не являются чисто теоретическими. Многие владельцы сайтов, приносящих доход, внесли изменения и рассчитывают на сохранение трафика после введения нового фактора ранжирования в действие.
Раньше Google фокусировал внимание на First Contentful Paint, но позже решил, что важно не просто отследить скорость загрузки первого контента, а измерить время, за которое подгружается самый тяжелый блок на странице. Эта метрика более понятна для вебмастеров и провести замер в режиме реального времени может каждый пользователь.
В Гугле прекрасно понимают, что при загрузке страницы контент может меняться. Например, рекламные объявления часто скачут туда-сюда потому что CSS срабатывает не сразу или возникают неполадки при загрузке скриптов. Поэтому при появлении новых больших элементов браузер отправляет анализаторам данные о LCP и надо ориентироваться на время работы последнего события.
Размер самого большого элемента на странице зависит от особенностей сайта. К примеру, в веб-версии Инстаграма LCP учитывает время загрузки логотипа, который появляется ещё до загрузки основного контента. Он становится доступен быстрее других блоков и «ждёт» когда появится форма входа и другие элементы.
Ещё одна распространённая ситуация подразумевает смещение приоритета. К примеру, в ходе загрузки самым большим элементом была картинка, а потом им стал текст, оформленный в виде цитаты. Анализаторы, которые считывают LCP, без проблем определяют самый большой элемент и фиксируют время его загрузки.
Необязательно разбираться в технических деталях, чтобы понять суть LCP и других метрик. Надо вникнуть в базовые особенности и потратить время на оптимизацию проекта, если рассчитываете на успешное продвижение в поисковой системе.
Почему метрика так важна?
Google ранее анонсировал, что с мая 2021 года фактор Page Experience станет частью основного алгоритма ранжирования, а Core Web Vitals войдут в его состав. Поэтому если сайт не проходит проверку по LCP и двум другим метрикам, со временем его видимость может упасть.
Пока нет никаких подтверждений того, что новый фактор ранжирования полностью изменил ситуацию в поисковой выдаче, но это может произойти в любой момент. И если вебмастер хочет и дальше зарабатывать на бесплатном трафике, надо подстроиться под новую реальность.
FID и CLS, входящие в состав «Основных интернет-показателей», тоже важны, но только в комплексе. Если оптимизировали одну метрику и рассчитываете на заметный результат, его может и не быть. Важно провести комплексную работу и постоянно мониторить ситуацию.
Метрика LCP важна потому что она:
- Учитывает самый большой блок на странице, на который браузер пользователя тратит больше всего ресурсов.
- Может влиять на индексацию ресурса. Google любит «выплёвывать» страницы с некачественным контентом, которые плохо раскрывают интент.
- Тесно связана с конверсией страницы и сайта. Мало кто будет оформлять заказ на проекте, который грузится несколько минут или зависает из-за высокой нагрузки.
- Позволяет определить качество ресурса. Если самым большим блоком будет реклама на всю высоту экрана браузера, LCP это покажет.
- Даёт понять юзеру, что контент на странице загружается и не надо закрывать вкладку браузера.
FID и CLS тоже важны в контексте пользовательского опыта, но можно сказать, что LCP на первом месте. Юзеры не любят долго ждать загрузки контента и могут покинуть страницу пока прогружается самый объемный блок. Поэтому надо постараться по максимуму оптимизировать значение метрики.
Как измерить показатель LCP?
Первая проблема, которая возникает у многих вебмастеров, касается не улучшения показателя LCP, а его проверки. Мало кто знает, как проводить тесты в режиме реального времени. Core Web Vitals уже давно есть в Google Search Console, но данные там обновляются с большой задержкой.
В отчете по скорости загрузки проекта в PageSpeed Insights чётко написано, что «Согласно данным наблюдений за последние 28 дней эта страница не отвечает требованиям к основным интернет-показателям». То есть алгоритмы анализируют значения метрик примерно в течение месяца.
К примеру, если вебмастер провёл масштабную работу по оптимизации и рассчитывает, что цифры мгновенно станут зелёными, его надежды не оправдаются. Обновление не происходит мгновенно и в некоторых случаях может затянуться надолго.
Если хотите проверить актуальное состояние Core Web Vitals, ориентироваться на данные из консоли для вебмастеров или цифры PageSpeed Insights не стоит. Ознакомиться с ними можно, но фактическое значение метрик может быть совсем другим.
Лучше проводить замеры в режиме реального времени, чтобы получить актуальные значения и зря не рассчитывать на преимущества от оптимизации. Не все знают, как это сделать, поэтому важно рассказать об инструментарии вебмастеров.
В Google уже давно уверены в том, что Core Web Vitals критически важны для оценки качества пользовательского опыта, поэтому инструменты для проверки значения метрик есть почти в каждом релевантном сервисе поисковой системы.
Есть несколько инструментов для замера LCP:
- Chrome User Experience Report. В отчете собраны анонимизированные данные пользователей с замером метрик. Ручные замеры делать не нужно потому что все цифры уже есть в отчёте. Данные из отчёта поступают в консоль для вебмастеров и PageSpeed.
- Chrome DevTools. Панель для разработчика в браузере позволяет выполнять замеры на стороне клиента. Инструмент можно использовать для быстрого получения значения метрик.
- web-vitals JavaScript library. На Гитхабе есть небольшая библиотека, которая позволяет быстро сделать замеры. На странице проекта доступна полная документация по работе с API.
- Lighthouse. Сервис загружает страницу в режиме эмуляции и не учитывает реальную ситуацию на устройстве пользователя. Поэтому ориентироваться на данные не стоит.
Учитывайте, что скорость загрузки сайта зависит от большого количества факторов. На конечные значения влияет скорость интернета, фоновая активность на устройстве и особенности поведения юзера. Поэтому замеры в режиме реального времени дадут чёткую картину и позволят сформировать комплексный отчёт.
Если по итогам замеров с разных устройств будет видно, что показатели Core Web Vitals очень плохие, надо срочно внедрять правки и подгонять метрики до входа в «зелёную зону». Иначе не стоит рассчитывать на высокие позиции.
Тем, кто не хочет разбираться в JS, API и других сложных инструментах, идеально подойдет консоль для разработчиков в браузере. Вот пошаговая инструкция по запуску теста Core Web Vitals:
- Откройте консоль разработчика в браузере.
- Переключитесь во вкладку Performance.
- Активируйте галочку Web Vitals.
- Нажмите иконку со стрелочкой и надписью Start profiling and reload page.
- Дождитесь окончания замеров и ознакомьтесь с данными.
На скриншоте ниже видно, что с LCP у проекта всё хорошо и FCP тоже в порядке. Но стоит провести дополнительные замеры с разных устройств, чтобы увидеть картину целиком и расслабиться, если всё в порядке.
Для замеров Core Web Vitals есть крутое расширение под Google Chrome, которое написано на основе библиотеки CWV. После запуска измерений данные считываются в режиме реального времени и отображаются в браузере практически мгновенно.
Установите его, откройте доступ к данным и нажмите на иконку в адресной строке. Ознакомьтесь с данными и заюзайте несколько дополнительных инструментов. Расширение показывает, что на VC.ru всё отлично с «Основными интернет-показателями», а у PageSpeed Insights противоположное мнение.
Дополнительно можно использовать GTmetrix и WebPage Test. Эти инструменты будут полезны вебмастерам и откроют более быстрый доступ к замерам метрик Core Web Vitals. Чтобы получить комплексные данные, используйте несколько тулзов одновременно.
Эффективные способы улучшения показателя LCP
Когда вебмастера видят, что их проекты не проходят проверку CWV, у них возникает задача оптимизировать показатель LCP. На этом моменте многие начинают судорожно искать плагины и сервисы, которые улучшают показатели в один клик.
Важно понять, что Core Web Vitals учитывают комплексные метрики. Нельзя просто минифицировать CSS и получить 100 баллов в PageSpeed Insights. Аналогичная ситуация и с LCP.
Чтобы разобраться с улучшением значения метрики, необходимо чётко понимать, что влияет на Largest Contentful Paint. Это поможет сформировать пошаговый план действий и последовательно выполнить все действия.
Отрисовка самого большого контента на странице должна происходить быстрее чем за 2,5 секунды. Всё, что дольше — проваленный тест Core Web Vitals и потенциальный риск для позиций в органической выдаче.
На LCP влияет несколько факторов:
- Время ответа сервера. Чем быстрее сайт откликнулся на запрос браузера пользователя, тем лучше.
- JavaScript и CSS с блокировкой рендеринга. Некоторые элементы на странице могут блокировать её отображение и пользователю приходится ждать загрузки. В идеальном состоянии блокирующих элементов не должно быть.
- Время загрузки ресурса. В 2021 году мало кто будет ждать загрузку контента несколько минут.
- Рендеринг на стороне клиента. Рендеринг в браузере с помощью Javascript, данные обрабатываются на устройстве пользователя.
Для оптимизации LCP надо понять, какой блок на странице является самым крупным и увидеть, насколько быстро он грузится. Время ответа сервера зависит от качества оптимизации на стороне хостинг-провайдера. Лучше выбирать хостинги, которые по умолчанию выдают хорошие показатели.
Для повышения скорости загрузки страницы можно использовать GZIP, CDN, а также технологии кэширования. Если речь идёт о сайте на базе WordPress, то вебмастерам доступны десятки плагинов для настройки кэша.
Дополнительные рекомендации:
- Оптимизируйте медиаконтент. Картинки лучше по максимуму сжать и конвертировать в формат WebP.
- Отложите загрузку второстепенных ресурсов. Асинхронная загрузка JS здорово помогает ускорить сайт.
- Сократите объем JS. Удалите все неиспользуемые скрипты, минифицируйте оставшиеся и объедините их в один файл.
- Используйте предварительный рендеринг. Он помогает защититься от перезагрузки сервера.
- Устраните элементы, блокирующие рендеринг. Данные о наличии таких блоков есть в отчёте PageSpeed Insights.
- Используйте критический CSS. Он помогает встроить главные стили в список ресурсов для приоритетной загрузки, а остальные правила отложить до момента взаимодействия пользователя с элементами.
Оптимизировать показатель LCP вручную без опыта и знаний очень сложно. Поэтому у типичного вебмастера есть два варианта — разобраться самостоятельно или заплатить программисту. Второй подход более комфортный потому что каждый сможет заняться своими задачами.
Ещё один выход из ситуации — покупка оптимизированных тем. Большое количество шаблонов на Themeforest и других маркетплейсах по умолчанию хорошо спроектированы. Остаётся соблюдать простые правила, чтобы сайт прошёл проверку Core Web Vitals и набрал хорошие баллы.
Если будете сотрудничать с прогером, не забывайте использовать инструменты для замера в режиме реального времени. И не ведитесь на предложения специалистов получить 100 баллов в PageSpeed. Обман алгоритмов не приведёт не даст ничего хорошего.
Какой показатель LCP считается хорошим?
Время загрузки самого большого контента не должно превышать 2,5 секунд.
Есть ли сервисы которые помогают оптимизировать показатели LCP?
Есть, но автоматизировать задачу очень сложно. Только если речь идёт о простой HTML-странице без админки. И даже в этом случае выйти на хорошие показатели без ручной настройки практически невозможно.
Можно ли не подгонять LCP?
Да, если хотите получать бесплатный трафик из Google.
Как часто обновляются данные об «Основных интернет-показателях» в консоли?
Раз в месяц, задержка может быть и больше. Ориентируйтесь на данные замеров в real-time.
Какие инструменты использовать для замеров?
Совмещайте несколько сервисов из нашей статьи. Например, расширение для Chrome и GTmetrix или WebPage Test.
A step-by-step guide on how to break down LCP and identify key areas to improve.
May 5, 2020 — Updated Sep 27, 2022
Largest Contentful Paint (LCP) is one of the three Core Web Vitals metrics, and it represents how quickly the main content of a web page is loaded. Specifically, LCP measures the time from when the user initiates loading the page until the largest image or text block is rendered within the viewport.
To provide a good user experience, sites should strive to have an LCP of 2.5 seconds or less for at least 75% of page visits.
There are a number of factors that can affect how quickly the browser is able to load and render a web page, and blockage or delays across any of them can have a significant impact on LCP.
It’s rare that a quick fix to a single part of a page will result in a meaningful improvement to LCP. To improve LCP you have to look at the entire loading process and make sure every step along the way is optimized.
Optimizing for LCP is a complex task, and with complex tasks it’s generally better to break them down into smaller, more manageable tasks and address each separately. This guide will present a methodology for how to break down LCP into its most critical sub-parts and then present specific recommendations and best practices for how to optimize each part.
LCP breakdown #
Most page loads typically include a number of network requests, but for the purposes of identifying opportunities to improve LCP, you should start by looking at just two:
- The initial HTML document
- The LCP resource (if applicable)
While other requests on the page can affect LCP, these two requests—specifically the times when the LCP resource begins and ends—reveal whether or not your page is optimized for LCP.
To identify the LCP resource, you can use developer tools (such as Chrome DevTools or WebPageTest) to determine the LCP element, and from there you can match the URL (again, if applicable) loaded by the element on a network waterfall of all resources loaded by the page.
For example, the following visualization shows these resources highlighted on a network waterfall diagram from a typical page load, where the LCP element requires an image request to render.
For a well-optimized page, you want your LCP resource request to start loading as early as it can, and you want the LCP element to render as quickly as possible after the LCP resource finishes loading. To help visualize whether or not a particular page is following this principle, you can break down the total LCP time into the following sub-parts:
This table explains each of these LCP sub-parts in more detail:
Every single page can have its LCP value broken down into these four sub-parts. There is no overlap or gap between them, and collectively they add up to the full LCP time.
When optimizing LCP, it’s helpful to try to optimize these sub-parts individually. But it’s also important to keep in mind that you need to optimize all of them. In some cases, an optimization applied to one part will not improve LCP, it will just shift the time saved to another part.
For example, in the earlier network waterfall, if you reduced the file size of our image by compressing it more or switching to a more optimal format (such as AVIF or WebP), that would reduce the resource load time, but it would not actually improve LCP because the time would just shift to the element render delay sub-part:
The reason this happens is because, on this page, the LCP element is hidden until the JavaScript code finishes loading, and then everything is revealed at once.
This example helps illustrate the point that you need to optimize all of these sub-parts in order to achieve the best LCP outcomes.
Optimal sub-part times #
In order to optimize each sub-part of LCP, it’s important to understand what the ideal breakdown of these sub-parts is on a well-optimized page.
Of the four sub-parts, two have the word «delay» in their names. That is a clue that you want to get these times as close to zero as possible. The other two parts involve network requests, which by their very nature take time.
Note that these time breakdowns are not strict rules, they’re guidelines. If the LCP times on your pages are consistently within 2.5 seconds, then it doesn’t really matter what the relative proportions are. But if you’re spending a lot of unnecessary time in either of the «delay» portions, then it will be very difficult to constantly hit the 2.5 second target.
A good way to think about the breakdown of LCP time is:
- The vast majority of the LCP time should be spent loading the HTML document and LCP source.
- Any time before LCP where one of these two resources is not loading is an opportunity to improve.
How to optimize each part #
Now that you understand how each of the LCP sub-part times should break down on a well-optimized page, you can start optimizing your own pages.
The next four sections will present recommendations and best practices for how to optimize each part. They’re presented in order, starting with the optimizations that are likely to have the biggest impact.
1. Eliminate resource load delay #
The goal in this step is to ensure the LCP resource starts loading as early as possible. While in theory the earliest a resource could start loading is immediately after TTFB, in practice there is always some delay before browsers actually start loading resources.
A good rule of thumb is that your LCP resource should start loading at the same time as the first resource loaded by that page. Or, to put that another way, if the LCP resource starts loading later than the first resource, then there’s opportunity for improvement.
Generally speaking, there are two factors that affect how quickly an LCP resource can be loading:
- When the resource is discovered.
- What priority the resource is given.
Optimize when the resource is discovered #
To ensure your LCP resource starts loading as early as possible, it’s critical that the resource is discoverable in the initial HTML document response by the browser’s preload scanner. For example, in the following cases, the browser can discover the LCP resource by scanning the HTML document response:
- The LCP element is an
<img>
element, and itssrc
orsrcset
attributes are present in the initial HTML markup. - The LCP element requires a CSS background image, but that image is preloaded via
<link rel="preload">
in the HTML markup (or via aLink
header). - The LCP element is a text node that requires a web font to render, and the font is loaded via
<link rel="preload">
in the HTML markup (or via aLink
header).
Here are some examples where the LCP resource cannot be discovered from scanning the HTML document response:
- The LCP element is an
<img>
that is dynamically added to the page via JavaScript. - The LCP element is lazily loaded with a JavaScript library that hides its
src
orsrcset
attributes (often asdata-src
ordata-srcset
). - The LCP element requires a CSS background image.
In each of these cases, the browser needs to run the script or apply the stylesheet—which usually involves waiting for network requests to finish—before it can discover the LCP resource and could start loading it. This is never optimal.
To eliminate unnecessary resource load delay, your LCP resource should always be discoverable from the HTML source. In cases where the resource is only referenced from an external CSS or JavaScript file, then the LCP resource should be preloaded, with a high fetch priority (more on fetch priority in the next section); for example:
<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/to/styles.css"><!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">
Optimize the priority the resource is given #
Even if the LCP resource is discoverable from the HTML markup, it still may not start loading as early as the first resource. This can happen if the browser preload scanner’s priority heuristics do not recognize that the resource is important, or if it determines that other resources are more important.
For example, you can delay your LCP image via HTML if you set loading="lazy"
on your <img>
element. Using lazy loading means that the resource will not be loaded until after layout confirms the image is in the viewport and so may begin loading later than it otherwise would.
Even without lazy loading, images are not initially loaded with the highest priority by browsers as they are not render-blocking resources. You can hint to the browser as to which resources are most important via the fetchpriority
attribute for resources that could benefit from a higher priority:
<img fetchpriority="high" src="/path/to/hero-image.webp">
It’s a good idea to set fetchpriority="high"
on an <img>
element if you think it’s likely to be your page’s LCP element—but limit this to just one or two images (based on common desktop and mobile viewport sizes), otherwise the signal becomes meaningless. You can also lower the priority of images that may be early in the document response, but isn’t visible due to styling, such as images in carousel slides that are not visible at startup:
<img fetchpriority="low" src="/path/to/carousel-slide-3.webp">
Deprioritizing certain resources can afford more bandwidth to resources that need it more—but be careful. Always check resource priority in DevTools and test changes with lab and field tools.
After you have optimized your LCP resource priority and discovery time, your network waterfall should look like this (with the LCP resource starting at the same time as the first resource):
2. Eliminate element render delay #
The goal in this step is to ensure the LCP element can render immediately after its resource has finished loading, no matter when that happens.
The primary reason the LCP element wouldn’t be able to render immediately after its resource finishes loading is if rendering is blocked for some other reason:
- Rendering of the entire page is blocked due to stylesheets or synchronous scripts in the
<head>
that are still loading. - The LCP resource has finished loading, but the LCP element has not yet been added to the DOM (it’s waiting for some JavaScript code to load).
- The element is being hidden by some other code, such as an A/B testing library that’s still determining what experiment the user should be in.
- The main thread is blocked due to long tasks, and rendering work needs to wait until those long tasks complete.
The following sections explain how to address the most common causes of unnecessary element render delay.
Reduce or inline render-blocking stylesheets #
Stylesheets loaded from the HTML markup will block rendering of all content that follows them, which is good, since you generally do not want to render unstyled HTML. However, if the stylesheet is so large that it takes significantly longer to load than the LCP resource, then it will prevent the LCP element from rendering—even after its resource has finished loading, as shown in this example:
To fix this, your options are to either:
- inline the stylesheet into the HTML to avoid the additional network request; or,
- reduce the size of the stylesheet.
In general, inlining your stylesheet is only recommended if your stylesheet is small since inlined content in the HTML cannot benefit from caching in subsequent page loads. If a stylesheet is so large that it takes longer to load than the LCP resource, then it’s unlikely to be a good candidate for inlining.
In most cases, the best way to ensure the stylesheet does not block rendering of the LCP element is to reduce its size so that it’s smaller than the LCP resource. This should ensure it’s not a bottleneck for most visits.
Some recommendations to reduce the size of the stylesheet are:
- Remove unused CSS: use Chrome DevTools to find CSS rules that aren’t being used and can potentially be removed (or deferred).
- Defer non-critical CSS: split your stylesheet out into styles that are required for initial page load and then styles that can be loaded lazily.
- Minify and compress CSS: for styles that are critical, make sure you’re reducing their transfer size as much as possible.
Defer or inline render-blocking JavaScript #
It is almost never necessary to add synchronous scripts (scripts without the async
or defer
attributes) to the <head>
of your pages, and doing so will almost always have a negative impact on performance.
In cases where JavaScript code needs to run as early as possible in the page load, it’s best to inline it so rendering isn’t delayed waiting on another network request. As with stylesheets, though, you should only inline scripts if they’re very small.
Don’t
<head>
<script src="/path/to/main.js"></script>
</head>
Do
<head>
<script>
// Inline script contents directly in the HTML.
// IMPORTANT: only do this for very small scripts.
</script>
</head>
Use server-side rendering #
Server-side rendering (SSR) is the process of running your client-side application logic on the server and responding to HTML document requests with the full HTML markup.
From the perspective of optimizing LCP, there are two primary advantage of SSR:
- Your image resources will be discoverable from the HTML source (as discussed in step 1 earlier).
- Your page content will not require additional JavaScript requests to finish before it can render.
The main downside of SSR is it requires additional server processing time, which can slow down your TTFB. This trade-off is usually worth it though because server processing times are within your control, whereas the network and device capabilities of your users are not.
A similar option to SSR is called static site generation (SSG) or prerendering. This is the process of generating your HTML pages in a build step rather than on-demand. If prerendering is possible with your architecture, it’s generally a better choice for performance.
Break up long tasks #
Even if you’ve followed the above advice, and your JavaScript code is not render-blocking nor is it responsible for rendering your elements, it can still delay LCP.
The most common reason this happens is when pages load large JavaScript files, which need to be parsed and executed on the browser’s main thread. This means that, even if your image resource is fully downloaded, it may still have to wait until an unrelated script finishes executing before it can render.
All browsers today render images on the main thread, which means anything that blocks the main thread can also lead to unnecessary element render delay.
3. Reduce resource load time #
The goal of this step is to reduce the time spent transferring the bytes of the resource over the network to the user’s device. In general, there are three ways to do that:
- Reduce the size of the resource.
- Reduce the distance the resource has to travel.
- Reduce contention for network bandwidth.
- Eliminate the network time entirely.
Reduce the size of the resource #
The LCP resource of a page (if it has one) will either be an image or a web font. The following guides go into great detail about how to reduce the size of both:
- Serve the optimal image size
- Use modern image formats
- Compress images
- Reduce web font size
Reduce the distance the resource has to travel #
In addition to reducing the size of a resource, you can also reduce the load times by getting your servers as geographically close to your users as possible. And the best way to do that is to use a content delivery network (CDN).
In fact, image CDNs in particular are a great choice because they not only reduce the distance the resource has to travel, but they also generally reduce the size of the resource—automatically implementing all of the size-reduction recommendations from earlier for you.
Reduce contention for network bandwidth #
Even if you’ve reduced the size of your resource and the distance it has to travel, a resource can still take a long time to load if you’re loading many other resources at the same time. This problem is known as network contention.
If you’ve given your LCP resource a high fetchpriority
and started loading it as soon as possible then the browser will do its best to prevent lower-priority resources from competing with it. However, if you’re loading many resources with high fetchpriority
, or if you’re just loading a lot of resources in general, then it could affect how quickly the LCP resource loads.
Eliminate the network time entirely #
The best way to reduce resource load times is to eliminate the network entirely from the process. If you serve your resources with an efficient cache-control policy, then visitors who request those resources a second time will have them served from the cache—bringing the resource load time to essentially zero!
And if your LCP resource is a web font, in addition to reducing web font size, you should also consider whether you need to block rendering on the web font resource load. If you set a font-display
value of anything other than auto
or block
, then text will always be visible during load, and LCP will not be blocked on an additional network request.
Finally, if your LCP resource is small, it may make sense to inline the resources as a data URL, which will also eliminate the additional network request. However, using data URLs comes with caveats because then the resources cannot be cached and in some cases can lead to longer render delays because of the additional decode cost.
4. Reduce time to first byte #
The goal of this step is to deliver the initial HTML as quickly as possible. This step is listed last because it’s often the one developers have the least control over. However, it’s also one of the most important steps because it directly affects every step that comes after it. Nothing can happen on the frontend until the backend delivers that first byte of content, so anything you can do to speed up your TTFB will improve every other load metric as well.
For specific guidance on this topic, see Optimize TTFB.
Monitor LCP breakdown in JavaScript #
The timing information for all of the LCP sub-parts discussed above is available to you in JavaScript through a combination of the following performance APIs:
- Largest Contentful Paint API
- Navigation Timing API
- Resource Timing API
The benefit to computing these timing values in JavaScript is it allows you to send them to an analytics provider or log them to your developer tools to help with debugging and optimizing.
For example, the following screenshot uses the performance.measure()
method from the User Timing API to add bars to the Timings track in the Chrome DevTools Performance panel.
Visualizations in the timings track are particularly helpful when looked at alongside the Network and Main thread tracks, because you can see at a glance what else is happening on the page during these timespans.
In addition to visualizing the LCP sub-parts in the timings track, you can also use JavaScript to compute what percentage each sub-part is of the total LCP time. With that information, you can determine whether your pages are meeting the recommended percentage breakdowns described earlier.
This screenshot shows an example that logs the total time of each LCP sub-part, as well as its percentage of the total LCP time to the console.
Both of these visualizations were created with the following code:
const LCP_SUB_PARTS = [
'Time to first byte',
'Resource load delay',
'Resource load time',
'Element render delay',
];new PerformanceObserver((list) => {
const lcpEntry = list.getEntries().at(-1);
const navEntry = performance.getEntriesByType('navigation')[0];
const lcpResEntry = performance
.getEntriesByType('resource')
.filter((e) => e.name === lcpEntry.url)[0];
// Ignore LCP entries that aren't images to reduce DevTools noise.
// Comment this line out if you want to include text entries.
if (!lcpEntry.url) return;
// Compute the start and end times of each LCP sub-part.
// WARNING! If your LCP resource is loaded cross-origin, make sure to add
// the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
const ttfb = navEntry.responseStart;
const lcpRequestStart = Math.max(
ttfb,
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
lcpResEntry ? lcpResEntry.requestStart || lcpResEntry.startTime : 0
);
const lcpResponseEnd = Math.max(
lcpRequestStart,
lcpResEntry ? lcpResEntry.responseEnd : 0
);
const lcpRenderTime = Math.max(
lcpResponseEnd,
// Prefer `renderTime` (if TOA is set), otherwise use `loadTime`.
lcpEntry ? lcpEntry.renderTime || lcpEntry.loadTime : 0
);
// Clear previous measures before making new ones.
// Note: due to a bug this does not work in Chrome DevTools.
LCP_SUB_PARTS.forEach((part) => performance.clearMeasures(part));
// Create measures for each LCP sub-part for easier
// visualization in the Chrome DevTools Performance panel.
const lcpSubPartMeasures = [
performance.measure(LCP_SUB_PARTS[0], {
start: 0,
end: ttfb,
}),
performance.measure(LCP_SUB_PARTS[1], {
start: ttfb,
end: lcpRequestStart,
}),
performance.measure(LCP_SUB_PARTS[2], {
start: lcpRequestStart,
end: lcpResponseEnd,
}),
performance.measure(LCP_SUB_PARTS[3], {
start: lcpResponseEnd,
end: lcpRenderTime,
}),
];
// Log helpful debug information to the console.
console.log('LCP value: ', lcpRenderTime);
console.log('LCP element: ', lcpEntry.element, lcpEntry.url);
console.table(
lcpSubPartMeasures.map((measure) => ({
'LCP sub-part': measure.name,
'Time (ms)': measure.duration,
'% of LCP': `${
Math.round((1000 * measure.duration) / lcpRenderTime) / 10
}%`,
}))
);
}).observe({type: 'largest-contentful-paint', buffered: true});
You can use this code as-is for local debugging, or modify it to send this data to an analytics provider so you can get a better understanding of what the breakdown of LCP is on your pages for real users.
Summary #
LCP is complex, and its timing can be affected by a number of factors. But if you consider that optimizing LCP is primarily about optimizing the load of the LCP resource, it can significantly simplify things.
At a high level, optimizing LCP can be summarized in four steps:
- Ensure the LCP resource starts loading as early as possible.
- Ensure the LCP element can render as soon as its resource finishes loading.
- Reduce the load time of the LCP resource as much as you can without sacrificing quality.
- Deliver the initial HTML document as fast as possible.
If you’re able to follow these steps on your pages, then you should feel confident that you’re delivering an optimal loading experience to your users, and you should see that reflected in your real-world LCP scores.
Last updated: Sep 27, 2022 — Improve article
Return to all articles
Руководитель группы оптимизаторов Webit
Прежде чем погрузиться в Web Vitals, стоит получить хотя бы простое представление о том, как происходит загрузка страницы в браузере.
Если упростить, то это работает так. Когда пользователь переходит на сайт, например из поисковой системы, через ссылку на другом сайте или просто перемещается с одной страницы на другую, то его браузер обращается к серверу, на котором расположена данная страница. Сервер обрабатывает полученный запрос, и если запрошенная страница действительно существует, то он отправляет ее содержимое.
Браузер получает HTML-код страницы сайта и начинает ее разбирать на отдельные элементы, пытаясь каждый тег перевести в (DOM) Document Object Model. В процессе разбора HTML браузер натыкается на внешние скрипты и стили, которые пытается загрузить. Парсер HTML будет продолжать работу по мере загрузки файла CSS, но он заблокирует рендеринг до тех пор, пока файл не будет загружен и проанализирован. Когда он встречает JS-файлы, то рендеринг так же блокируется, но у JS-файлов есть преимущество в виде атрибутов defer и async, которые позволяют HTML-парсеру продолжать работу, пока JS выполняется в фоне. Также в процессе загрузки CSS формируется CSSOM (CSS Object Model), которая содержит в себе карту всех CSS-селекторов сайта.
После всего этого браузер создает дерево рендеринга, в котором объединяет CSS и HTML. Для каждого узла дерева рендеринга происходит расчет того, где он будет находиться на странице. И уже после этого браузер идет по этому дереву и отрисовывает страницу.
Если в процессе подключается много отдельных файлов либо используется объемное дерево DOM, или файлы, которые отправляет сервер, достаточно большие, либо сам сервер «слабый» и т.д., то это приводит к тому, что страница может очень долго загружаться на устройстве.
Никому не нравится, когда страница долго загружается, из-за этого пользователи могут покидать сайт, не дождавшись загрузки. Это одна из причин, по которой поисковые системы стараются дать «бонус» в ранжировании сайтам с лучшей скоростью загрузки.
Дополнительно к этому в мае 2020 года Google представил Web Vitals – важные показатели для сайта, которые начнут использоваться в ранжировании с середины июня 2021 года.
Важно понимать, что это лишь один из дополнительных факторов ранжирования. В области поискового продвижения все так же важен качественный контент, корректная индексация сайта, коммерческие, поведенческие и другие факторы.
То есть, если мы сделаем идеальные показатели Web Vitals, но страницы сайта не будут отвечать на запросы пользователей, это не приведет в ТОП.
Необходимо правильно оценивать приоритетность данных параметров по отношению ко всем остальным. Однако при прочих равных сайту с лучшими показателями Web Vitals будет предоставлено более высокое место в поисковой выдаче, чем аналогичным сайтам.
На текущий момент всего около 20% сайтов соответствуют рекомендуемым Google значениям (по данным https://corewebvitals.iprospect.com/).
Хочется добавить, что есть ряд лайфхаков, как обмануть «улучшить» любой из показателей. В этой статье нет таких решений, так как стоит помнить, что любые хитрости в обход качественных решений проблем улучшают количественные показатели для поисковых систем, но ухудшают пользовательский опыт взаимодействия с сайтом, и в конечном счете влияют скорее негативно.
Ниже я постараюсь рассказать вам про каждый показатель подробнее, а именно – максимально просто объяснить каждый из показателей и то, как на него можно качественно влиять. Также подробнее раскрою стандартную рекомендацию «Улучшить показатели скорости загрузки сайта», чтобы добавить конкретики: «куда смотреть/что править».
Для начала немного условных обозначений которые будут встречаться в статье:
LCP (Largest Contentful Paint) – показывает, за какое время самый большой контент отрисовался в видимой части пользователя (на первом экране).
FID (First Input Delay) – накопленные данные, показывающие среднее время реагирования браузера на первое действие пользователя.
TBT (Total Blocking Time) – общее время блокировки.
CLS (Cumulative Layout Shift) – совокупный сдвиг макета.
FCP – первая отрисовка содержимого (не путайте с LCP!).
TTI – время до интерактивности.
Лабораторные данные – данные для одного измерения скорости загрузки сайта.
Полевые или накопленные данные – средние значения множества данных, основанных на множестве загрузок той или иной страницы пользователями.
Область просмотра – это логическое разрешение экрана пользователя.
Все эти показатели можно увидеть в PageSpeed Insights.
Рассмотрим на примере сайта https://alliancesales.ru/. Область просмотра в данном случае – это скриншот экрана справа от значений.
Основные показатели, на которые будет смотреть Google, это:
1. Largest Contentful Paint (LCP)
LCP показывает, за какое время самый большой контент отрисовался в видимой части пользователя (на первом экране). Например, для главной страницы https://alliancesales.ru/ самым большим контентом является баннер.
Хорошим показателем будет считаться показатель до 2,5 секунд для 75% пользователей.
Посмотреть текущий показатель можно в сервисе Google Page Speed. Данный сервис представляет как лабораторные данные – для конкретной проверки, так и накопленные статистические данные.
Например, вот показатели для страницы https://alliancesales.ru/ для мобильных устройств (важно соответствовать и на мобильных, и на ПК):
Мы видим, что накопленные данные говорят о том, что среднее время отрисовки основного видимого контента составляет 3 секунды. Для 65% пользователей – менее 2-х секунд, однако для 13% пользователей данный показатель находится в «красной» зоне.
Лабораторные данные говорят, что показатель гораздо хуже, и составляет 14,9 секунд.
Какие элементы входят в LCP при его подсчете:
- < img > (как в нашем примере),
- < image > элементы внутри < svg > (могут входить),
- < video > (могут входить),
- элементы с фоновым изображением, загруженным с помощью CSS,
- элементы уровня блока, содержащие текстовые узлы или другие дочерние текстовые элементы встроенного уровня (например div с текстом внутри, скриншот ниже).
Однако если элемент выходит за пределы области просмотра, если какой-либо элемент обрезан или имеет невидимое переполнение (например, часть текста спрятана под спойлер или скролл), то эти части не учитываются в размере элемента.
Примеры для лучшего понимания
Пример 1.
В данном случае в первый момент отрисовки (FCP – шаг 1) у нас появляется контент под логотипом – он является самым большим контентом.
Шаг 2–4 – у нас под логотипом появился текстовый блок, который занимает большую область экрана. На последней стадии загрузки первого экрана (шаг 5) – появилась картинка, которая стала самым большим контентом. Время до отображения данной картинки и будет показывать показатель LCP.
Пример 2.
В данном случае в момент первой отрисовки контента (FCP – шаг 1) на сайте появляется текстовый блок, который занимает самую большую часть экрана. На втором шаге подгрузились миниатюры, однако самый большой контент остался прежним. На третьем шаге у нас появился дополнительный контент, что привело к смещению прежнего самого крупного контента вниз, а самым крупным контентом стал другой текстовый блок. Четвертый шаг лишь немного сместил контент ниже. А вот на пятом шаге, в момент последней стадии загрузки первого экрана, снова появилась картинка, которая и стала самым крупным контентом в области просмотра.
В примерах, указанных выше, самый большой элемент изменяется по мере загрузки содержимого. В первом примере новый контент добавляется в DOM, и самым большим становится другой элемент. Во втором примере меняется макет, а содержимое, которое ранее было самым большим, удаляется из области просмотра.
Еще несколько примеров:
В первом примере логотип Instagram загружается относительно рано и остается самым крупным элементом, даже когда другой контент отображается постепенно.
В примере страницы результатов поиска Google самый большой элемент – это абзац текста, который отображается до того, как любое из изображений завершит загрузку. Поскольку все отдельные изображения меньше этого абзаца, он остается самым большим элементом на протяжении всего процесса загрузки.
Внимание! Показатель LCP отличается для разных типов страниц и разных страниц одного типа.
Как улучшить LCP
На LCP в первую очередь влияют четыре фактора:
- Медленное время ответа сервера (например, скорость работы базы данных; скорость выполнения скриптов на сервере; все, что происходит на back-end; а также удаленность сервера от пользователя, скорость интернета).
- JavaScript и CSS с блокировкой рендеринга (в первую очередь вставлять в код только критичный CSS и JS, остальное можно подгружать позже, чтобы не происходило блокировки основного потока (использовать lazy-load)).
- Время загрузки ресурса (нужно уменьшать размер передаваемых файлов).
- Клиентский рендеринг (актуально для SPA).
Подробные сведения о том, как улучшить LCP, указаны в разделе Оптимизация LCP (данная информация скорее относится к программистам, чем к SEO-специалистам, однако нам нужно понимать, о чем идет речь и где это можно найти).
Желательно также знать основные методы повышения производительности сайта, которые могут улучшить LCP:
- Применение PRPL (предварительная загрузка, ускорение отрисовки, кеширование, lazy-load).
- Оптимизация процесса визуализации/отрисовки (например, использовать прогрессивный рендеринг страниц с подгрузкой JS-файлов по мере необходимости).
- Оптимизация CSS (например, сделать загрузку CSS асинхронной, подгружая файлы через JS).
- Оптимизация изображений (использовать современные форматы изображений, использовать прогрессивное сжатие изображений и т.п.).
- Оптимизация веб-шрифтов (например, избегать невидимого текста, уменьшить размер шрифтов/включить сжатие).
- Оптимизация JavaScript для сайтов с клиентским отображением – SPA-сайты, JS-frameworks (например, чтобы HTML-контент формировался в браузере пользователя с помощью JS, а не на сервере).
Проработка LCP
Данные по всем проблемным страницам можно найти в Google Search Console (требуется авторизация) https://search.google.com/u/1/search-console/core-web-vitals. Это касается только тех сайтов, где достаточно «полевых данных». Если «полевых» данных нет, а также в GSC нет никаких ошибок, то стоит самостоятельно проверить основные типы страниц через Google Page Speed для оценки наличия полевых и лабораторных данных LCP.
Дальше необходимо найти причины столь низких значений LCP. Напоминаю, что показатель хуже чем 4 секунды, считается плохим. Желательно добиться показателя ниже 2,5 секунд.
Посмотрим на примере страницы https://alliancesales.ru/. По данным Google Page Speed, наш LCP равен 14,9 секунд (лабораторные).
При просмотре через сервис https://gtmetrix.com/ LCP составляет только 4,7 секунды.
При просмотре через инспектор браузера Google Chrome (кнопка F12, далее перейти на вкладку Performance, включить Screenshots, переключиться в мобильные устройства (например, iPhone X)):
После чего запустить проверку Ctrl + Shift + E (в Windows). Видим, что в разделе Timings есть блок LCP.
LCP составляет 5,9 секунды. Также мы видим связанный блок, который как раз считается самым большим в области видимости для клиента (при наведении на div мы видим, какой конкретно элемент считается самым большим на экране).
Итого три разных инструмента нам показали 3 разных показателя: Google Page Speed – 14,9 секунд; GTmetrix – 4.7 секунды; Инспектор браузера – 5,9 секунд.
Не забываем, что на время LCP влияет время ответа сервера, которое может постоянно меняться, а также напрямую зависит от расстояния до сервера и количества узлов в цепочке соединения.
Рекомендации
- Необходимо увеличить мощность сервера для сокращения времени его ответа.
- Так как наша картинка товара является наибольшим контентом на странице, то для изображения первого товара можно использовать preload.
- Добавление CDN.
- Прочие рекомендации из раздела «Как улучшить LCP».
2. First Input Delay (FID)
FID – время до интерактивности вашего сайта.
FID измеряет время от момента, когда пользователь впервые взаимодействует со страницей (то есть, когда он щелкает ссылку, нажимает кнопку или использует настраиваемый элемент управления на основе JavaScript), до момента, когда браузер действительно может начать обработку событий в ответ на это взаимодействие. Хорошим показателем будет считаться до 100 миллисекунд для 75% пользователей.
Важно! FID измеряет только «задержку» обработки событий. Он не измеряет ни время обработки событий, ни время, необходимое браузеру для обновления пользовательского интерфейса после запуска обработчиков событий.
Постараемся понять, что же это такое, на простом примере.
Условные обозначения:
FCP – первая отрисовка содержимого (не путайте с LCP!).
TTI – время до интерактивности.
Серые блоки – запросы на ресурсы (в основном CSS и JS).
Желтые блоки – периоды, когда основной поток отображения страницы в браузере на некоторое время занят.
Вертикальная черная линия рядом с красной стрелкой – момент взаимодействия пользователя.
В этом примере пользователь случайно взаимодействовал со страницей в начале периода наибольшей нагрузки основного потока (смотрим скрин – указано стрелкой). Если бы пользователь взаимодействовал со страницей мгновением раньше (во время периода простоя), браузер мог бы ответить сразу. Поскольку ввод происходит, когда браузер находится в процессе выполнения задачи, он должен дождаться завершения задачи, прежде чем сможет ответить на ввод. Время ожидания – это значение FID для этого пользователя на этой странице.
Хотя задержка от любого ввода может привести к плохому взаимодействию с пользователем, ориентироваться стоит именно на задержку первого ввода.
FID – это показатель, который измеряет скорость отклика страницы во время загрузки. Таким образом, он фокусируется только на событиях ввода от действий, таких как щелчки, касания и нажатия клавиш.
Важно также понимать, что не все пользователи будут взаимодействовать с сайтом при каждом посещении. Кроме того, первые взаимодействия некоторых пользователей могут происходить в момент загрузки потока (желтые блоки), а также могут происходить в моменты, когда основной поток простаивает.
К сожалению FID нельзя измерить в лабораторных условия, так как необходимо наличие реального пользователя. Однако показатель общего времени блокировки (TBT) (время выполнения задачи в потоке, превышающее 50 мс) можно измерить в лабораторных условиях, к тому же он хорошо коррелирует с FID. То есть улучшение TBT также должно улучшать FID.
Для примера посмотрим показатели страницы https://alliancesales.ru/.
Видим, что среднее значение полевых измерений составляет 91 миллисекунду. 75% пользователей имели FID менее 100 миллисекунд. Для 13% пользователей показатель FID более 300 миллисекунд. Лабораторные данные по TBT составили 4050 миллисекунды. То есть основной поток в браузере был заблокирован различными задачами чуть больше 4-х секунд.
Как улучшить FID
Хотя FID является полевым показателем, рекомендации по улучшению FID такие же, как и для улучшения лабораторного показателя Total Blocking Time (TBT).
Частично рекомендации, которые могут улучшить показатель FID, такие:
- Уменьшить влияние стороннего кода (удалить либо уменьшить код со сторонних сайтов/приложений).
- Уменьшить время выполнения JavaScript (например, сократить или сжать код, удалить неиспользуемый код, использовать асинхронную загрузку).
- Уменьшить основной рабочий поток (например, следует избегать больших и сложных макетов, минимизировать CSS, удалить неиспользуемый код и многое другое).
- Сохранить низкое количество запросов и небольшие размеры переводов (самое простое – уменьшить размеры крупных файлов при передаче).
Проработка FID (TBT)
Данные по всем проблемным страницам можно найти в https://search.google.com/u/1/search-console/core-web-vitals (требуется авторизация), это касается только тех сайтов, где достаточно «полевых данных». Если «полевых» данных нет, а также в GSC нет никаких ошибок, то стоит самостоятельно проверить основные типы страниц через Google Page Speed для оценки наличия полевых данных FID и лабораторных данных TBT.
Напоминаю, что показатель хуже, чем 300 миллисекунд, считается плохим. Желательно добиться показателя ниже 100 миллисекунд.
Из списка страниц, которые содержит в себе отчет в Google Search Console, необходимо выбрать основные шаблонные страницы с наихудшими показателями. Для примера возьмем https://alliancesales.ru/.
Можно проверить показатели FID (TBT) в Google Page Speed. Для более детального подхода можно воспользоваться инспектором браузера.
В инспекторе браузера Google Chrome (кнопка F12) необходимо перейти на вкладку Lighthouse, выбрать мобильные устройства и Performance, после этого нажать Generate report.
Получим следующую картину.
Внимание! Могут появляться предупреждения, поэтому проделывайте данные операции в «чистом» браузере.
Видим, что показатель TBT составил 3,0 секунд.
Чтобы сократить показатель ТВТ, необходимо провести детальный анализ всех компонентов и выявить, где кроются длинные задачи, которые превышают рекомендованные 50 миллисекунд. Среди наиболее частых причин следующие:
- Ненужная загрузка или выполнение JavaScript. Это происходит, когда основной поток выполняет работу, которая на самом деле не нужна для загрузки страницы. Сокращение нагрузки JavaScript с помощью разделения кода, удаления неиспользуемого кода или эффективной загрузки стороннего JavaScript должно улучшить ваш показатель TBT.
- Неэффективные операторы JavaScript. Например, после анализа вашего кода можете увидеть вызов document.querySelectorAll(‘a’) (выбор всех ссылок на странице), который возвращает 2000 узлов. В данном случае требуется провести рефакторинг кода для использования более конкретного селектора, который возвращает только 10 узлов, а это улучшит показатель TBT.
Рекомендации
Рассмотрим на примере страницы https://tomdom.ru/vladivostok/komplekti-shtor/.
Используем инспектор браузера Google Chrome (F12). Переходим на вкладку Lighthouse, ставим категорию Performance для мобильный устройств. Жмем кнопку «Generate report» (подобные данные можно получить и через Google Page Speed, однако зачастую приходится проверять что-то на тестовом сервере, который закрыт для роботов, поэтому мы используем DevTools).
Получаем следующие данные и возможные рекомендации по оптимизации.
Стрелками указаны основные распространенные причины, которые могут влиять на TBT и, как следствие, на FID. Посмотрим на них более детально и постараемся в общих чертах понять, что мы можем с этим сделать.
Неиспользуемый код JS/CSS
Суть состоит в том, что не весь код JS или CSS нужен на той или иной странице, поэтому рекомендуется данные файлы разбивать и подгружать только на тех страницах, где они непосредственно используются. Однако это может перерасти в полный рефакторинг кода всего сайта.
На обычном сайте достаточно сложно отрефакторить ВЕСЬ код таким образом, чтобы необходимый код грузился только на нужной странице. Обычно это либо невозможно, либо занимает гигантское количество времени, так как придется поменять саму архитектуру фронтенда на сайте. Не у каждого проекта есть ресурсы на это. А вот на сайтах, построенных по принципам SPA, такой подход возможен. Например, можно использовать асинхронную загрузку JS-кода компонентов.
На скриншоте ниже видно, как загрузилось множество JS-файлов, каждый из которых отвечает либо за свой компонент на странице, либо за код самой страницы в целом.
Но стоит перейти на другую страницу, как мы увидим (следующий скриншот), что подгрузился еще JS, как раз тот, который нужен именно для новой страницы.
Такой подход позволяет нам ускорять загрузку при первом заходе пользователя на страницу и не загружать ему лишние ресурсы.
Устраните ресурсы, блокирующие отображение
На этот параметр влияет время выполнения JS и CSS и то, как они подключаются на страницу. В идеале весь JS должен подключаться асинхронно, но не везде это реально сделать. Да и с CSS нужно быть осторожнее, а то получится, что весь CSS грузится асинхронно, и тогда пользователь во время загрузки будет видеть «голую» HTML-страницу без оформления. А «расстановка» всех элементов на свои места произойдет только после того, как загрузится CSS.
Кстати, при таком подходе будет происходить сдвиг макета, о котором написано ниже. Как раз для этого необходимо в сам HTML включить критический CSS, то есть основной, чтобы пользователь в первые секунды видел хоть как-то оформленную страницу, а потом подключать уже остальной CSS. Но не на каждом проекте это возможно из-за начальной архитектуры CSS-кода. Тут либо рефакторить (что иногда по времени может занять даже больше времени, чем его первоначальное написание), либо не трогать.
Уменьшение влияния стороннего кода
Тут все просто. Обычно этот параметр завышен, когда на сайт внедрено большое количество разнообразных сторонних скриптов, таких как Яндекс.Метрика и Google Analytics. Поэтому очень важно загружать их так, чтобы они не блокировали основной поток выполнения рендеринга.
Например, Яндекс.Метрика в последнем обновлении выкатила «асинхронность» счетчика по умолчанию. Другие внешние скрипты можно подключать, используя атрибуты async или defer.
3. Cumulative Layout Shift (CLS)
CLS – показатель стабильности макета, или, по-другому, «накопительный сдвиг макета».
Как это примерно выглядит https://www.webit.ru/images/layout-instability2.mp4 .
На видео пользователь хочет нажать «Нет», но макет сдвигается и клик приходится на «Да, отправить мой заказ». Дальше можно наблюдать многократное нажатие на кнопку отмены :).
То есть мы находимся на сайте, но с загрузкой сайта контент частично смещается. CLS измеряет общую сумму всех индивидуальных оценок сдвига макета для каждого неожиданного сдвига макета, который происходит в течение всего срока загрузки страницы.
Сдвиг макета происходит каждый раз, когда видимый элемент изменяет свое положение от одного визуализируемого кадра к другому. Хорошим CLS будет считаться показатель не выше 0,1 для 75% пользователей сайта.
CLS можно измерить как в полевых условиях, так и лабораторных. Например для страницы карточки товара на нашем исследуемом сайте https://alliancesales.ru/catalog/perchatki/perchatki_nitrilovye/perchatki_nitrilovye_benovy_dental_formula_chernye_50_par_up/ сдвиг макета для мобильных устройств:
Средний показатель для «полевых» данных составляет 0,39. Только для 46% пользователей CLS меньше чем 0,1.
Лабораторные данные показывают CLS 0,475, то есть происходит сдвиг макета на величину, которая не входит в рекомендуемые показатели.
Как улучшить CLS
Для большинства веб-сайтов вы можете избежать всех неожиданных сдвигов в макете, придерживаясь нескольких принципов:
- Всегда включайте атрибуты размера в свои изображения и видеоэлементы или иным образом резервируйте необходимое пространство. Такой подход гарантирует, что браузер сможет выделить правильный объем места в документе во время загрузки изображения.
- Никогда не вставляйте контент поверх существующего контента, кроме как в ответ на взаимодействие пользователя.
- Анимируйте переходы таким образом, чтобы обеспечить контекст и непрерывность от состояния к состоянию.
Подробные сведения о том, как улучшить CLS можно прочесть в руководстве по оптимизации.
Проработка CLS
Данные по всем проблемным страницам можно найти в https://search.google.com/u/1/search-console/core-web-vitals (требуется авторизация. Это касается только тех сайтов, где достаточно «полевых данных». Если «полевых» данных нет, а также в GSC нет никаких ошибок, то стоит самостоятельно дополнительно проверить основные типы страниц через Google Page Speed для оценки лабораторных данных показателя CLS.
На примере сайта https://tomdom.ru:
Стоит отметить, что в большинстве случаев сдвиг макета происходит шаблонными элементами. То есть исправление проблем для одной страницы может также исправить проблемы для множества других.
На текущий момент проблема наблюдается только на мобильных устройствах. На ПК проблемных URL не найдено:
Напоминаю, что показатель хуже, чем 0,25, считается плохим. Желательно добиться показателя ниже 0,1.
Из списка страниц, которые содержит в себе отчет в Google Search Console, необходимо выбрать основные шаблонные страницы с наихудшими показателями. Вернемся к нашей странице https://alliancesales.ru/catalog/perchatki/perchatki_nitrilovye/perchatki_nitrilovye_benovy_dental_formula_chernye_50_par_up/.
В инспекторе браузера Google Chrome (кнопка F12) необходимо перейти на вкладку Performance, включить Screenshots, переключиться в мобильные устройства (например iPhone X).
После чего запустить проверку Ctrl + Shift + E (в Windows). Мы получим картинку:
Нас интересует раздел Experience. В нем содержится 4 блока, которые говорят нам, что сдвиг макета происходил четыре раза. При изучении трех последних блоков, сдвиг макета был соответственно на: 0,021, 0,01 и 0,00005 – это очень низкий показатель, и на подобные минимальные сдвиги можно не обращать внимание (напоминаю, наша задача чтобы сдвиг макета был ниже 0,25 и желательно ниже 0,1).
Важно! Тут действует накопительная система. То есть в расчет берется СУММАРНОЕ значение всех сдвигов.
При просмотре первого блока сдвиг макета составил 0,5352.
Итого, основной сдвиг макета пришелся на первый блок.
Постараемся понять, где именно происходит сдвиг макета.
При наведении на соответствующие строки «Moved from/to» у нас происходит подсветка элемента, который сместился.
Визуально сдвиг макета выглядит так https://www.webit.ru/images/EQ4C7FfpIT.gif. То есть произошло смещение макета вниз.
Рекомендации
Необходимо скорректировать макет сайта таким образом, чтобы контент загружался уже непосредственно на ожидаемом месте, без смещения.
P. S. Если копать дальше, то можно разобраться, что конкретно сдвинуло наш макет. Начать можно со связанного узла (выше на скрине есть Related Node). В нашем случае подгрузилась иконка корзины, из-за чего произошел сдвиг иконки мобильного телефона. Другие сдвиги можно также отследить и разобраться, что конкретно повлияло на сдвиг того или иного элемента.
В данном случае необходимо зарезервировать место под иконку корзины таким образом, чтобы иконка мобильного телефона загружалась сразу в необходимом месте, без сдвига.
Выводы
Параметры Web Vitals безусловно важные, однако, как было указано в начале нашей статьи, на сегодняшний день всего около 20% сайтов соответствуют рекомендуемым показателям. Поэтому в первую очередь необходимо оценить объем текущих проблем на сайте и степень их влияния на ранжирование проекта.
При устранении ошибок стоит обратить внимание на параметры с большой долей пользователей в красной зоне для полевых данных. А в качестве решений выбирать те методы, которые сразу затронут максимальное количество страниц на сайте с привлечением минимальных ресурсов программистов и верстальщиков.
Largest contentful paint is the core web vital people struggle with most.
Google’s video on optimizing LCP is a great watch and breaks LCP into 4 parts: TTFB, resource load delay, resource load time, and element render delay. Philip gives solid recommendations to improve each part, but they’re not WordPress-specific (pretty much why I wrote this tutorial).
For example, it’s hard to mention TTFB without talking about Cloudflare Enterprise + full page caching. Cache plugins have specific settings that can help (or hurt) LCP. Themes/plugins that add lots of CSS/JavaScript impact it too. Follow these tips and I bet your LCP will be under 2.5s.
LCP measures how long it takes the main content to load. People struggle with LCP because there are lots of factors. Your above the fold content is a good place to start.
Largest Contentful Paint | Score |
---|---|
0 – 2.5s | Good |
2.5 – 4s | Needs Improvement |
Over 4s | Poor |
1. Learn Which LCP Parts You Need To Work On
Largest contentful paint is broken down into 4 sub-parts. Skip to 12:40 in Google’s video for quick tips to improve each part. Otherwise, I listed tips below.
LCP Sub-Part | Factors | LCP % |
---|---|---|
TTFB | Primarily hosting and CDNs + full page caching | ~40% |
Resource load delay | Exclude above the fold content from optimizations, resource hints | <10% |
Resource load time | Reduce image/CSS/JS sizes, critical CSS, CDN, cache expiration | ~40% |
Element render delay | Render-blocking CSS/JS, JS file size, font-display optional | <10% |
Tools
- KeyCDN Performance Test – measures TTFB in 10 global locations.
- Waterfall Chart – nice visualization showing which files are contributing to LCP.
- PSI Recommendations – many recommendations in PageSpeed Insights are correlated with LCP. Fixing recommendations shown in opportunities/diagnostics reports can help.
- Chrome Dev Tools Coverage Report – large, unoptimized CSS/JS files are one of the biggest LCP factors. This can help you find which plugins and third-party JavaScript take longest to load. The plugin names and third-party domains are usually listed in the URL.
2. Exclude Above The Fold Images From Lazy Load
Above the fold images should be shown immediately, but lazy load delays them and adds to the “resource load delay” part of LCP.
It can be time consuming to go through every single page/post and exclude these images manually. While logos and top sidebar images may be universal across most of your website, your top post image (#3 in the screenshot below) is often unique for every single page and post.
They also happen to be my largest contentful paint element for most posts:
Preloading critical images is usually the best method. Not only does it preload above the fold images, but it also excludes them from lazy load. It’s supported by Perfmatters and FlyingPress. Just set the number of images usually shown above the fold and the plugin will handle the rest.
You can also exclude leading images, but it won’t preload them.
If your cache plugin doesn’t support either of these, you’ll need to manually go through your pages/posts, copy all image URLs loading above the fold, then exclude them manually. Some cache plugins have exclusion methods which you should be able to find in their documentation.
Background Images
Background images aren’t lazy loaded since they’re often loaded from a separate CSS file. Some cache plugins have a lazy-bg helper class to lazy load them while WP Rocket requires moving them to inline HTML. Since they’re not lazy loaded, there’s usually no need to exclude above the fold background images, but you’ll need to lazy load these manually if they load below the fold.
Elementor Image Widgets
Elementor image widgets aren’t excluded from lazy load by default since they don’t use img tags. Cache plugins sometimes have a skip-lazy helper class for excluding images manually.
Optimizing Above The Fold Images Is Key
Just like you would optimize any image on your site, it’s even more important to do this for above the fold images. Compress them, use correct dimensions, faster image formats (i.e. WebP), and serve smaller image sizes to mobile devices via CDNs or an adaptive images plugin.
3. Prioritize Above The Fold Images
If you’re preloading critical images shown in the previous step, you shouldn’t need to do anything since above the fold images are already being prioritized and excluded from lazy load.
However, preload has drawbacks and Google recommends only using it for background LCP images, then using fetchpriority especially for your LCP image shown in PageSpeed Insights.
Here, we’re giving the LCP image a high fetchpriority while using the faster WebP version.
<link fetchpriority="high" rel="preload" href="/LCP-image.webp" as="image">
As of writing this, FlyingPress is the only cache plugin I know that supports fetchpriority shown in their changelog in version 3.9.0.
Another Challenge For Background Images
If your LCP image is a background image and loads in a separate CSS file like Elementor does, your LCP image won’t be preloaded. You need to move the background image to inline HTML and preload it, or preload both the background image and the CSS file the image is located in.
“To eliminate unnecessary resource load delay, your LCP resource should always be discoverable from the HTML source. In cases where the resource is only referenced from an external CSS or JavaScript file, then the LCP resource should be preloaded.”
4. Reduce CSS/JavaScript Sizes
Resource load time is 40% of LCP and CSS/JS are usually your largest files.
View your Chrome Dev Tools coverage report and look at the URLs which usually tell you whether certain plugins, themes, third-party JavaScript, or other files add the most bytes.
Summary
- Themes – the last thing you want to do is start with a bloated theme/page builder and install multiple heavy page builder plugins. Elementor/Divi are notoriously slow while Gutenberg is lightweight. GeneratePress, Blocksy, Kadence for the win.
- Plugins – the coverage report shows which plugins add the most CSS/JavaScript. Try moving plugin-dependent content below the fold like social sharing plugins and image galleries. Mega menus are awful for LCP since not only do they add CSS/JS, but they also add it above the fold on every single page of your website.
- Remove Unused CSS – WP Rocket’s is slower than FlyingPress, Perfmatters, and LiteSpeed Cache as it loads used CSS inline instead of a separate file. Separate file is faster for visitors since the file can be cached and it doesn’t increase HTML size.
- Minify – strips unnecessary characters from CSS/JS which reduces their file size.
- Third-Party Code – start by hosting files locally (fonts, analytics, using local avatars for comments, YouTube preview images and thumbnails, etc). The rest of third-party code can usually be delayed. A common reason you’ll see this error in PSI is overtracking. Do you really need Google Analytics, Tag Manager, Heatmaps, Facebook Pixel, New Relic, and other tracking tools? Consider removing some of them. Perfmatters does an excellent job at reducing the size of GA tracking codes.
- Asset unloading plugins – Perfmatters and Asset CleanUp are two popular plugins for removing individual CSS/JS files (or entire plugins) on specific content.
- Page builder optimizations – Elementor Experiments and Divi’s built-in performance settings have several options to reduce the size of CSS, JS, and fonts.
- Code header in CSS – don’t use slow page builders (or plugins) for your header or menus. Code them in CSS instead. It’s much faster than bloated page builder code.
- Remove files you don’t use – icons, Gutenberg CSS, jQuery, emojis, elementor-dialog, and other individual files can be removed/dequeued when not using them.
5. Reduce TTFB
TTFB alone is 40% of LCP and is explained in Google’s video at 5:24. This is mainly your hosting (and CDN).
Rocket.net with their free Cloudflare Enterprise will outperform any “mainstream host” since you get 32 CPU cores + 128GB RAM, NVMe storage, Redis, and Cloudflare’s full page caching + Argo Smart Routing. I use them and average a <150ms global TTFB (or click through my posts).
12 things to know about hosting/TTFB
- Hosting is the #1 factor of site speed.
- TTFB is a key indicator of hosting performance.
- TTFB is part of core web vitals and is 40% of LCP.
- TTFB also affects INP (since latency is part of TTFB).
- SpeedVitals tests TTFB in 35 locations – use this tool!
- Test your site 3 times to get accurate numbers in SpeedVitals.
- Doing this ensures your caching and CDN are working properly.
- Check your average TTFB worldwide in your 3rd SpeedVitals test.
- Google flags your TTFB if it’s over 600ms, but under 200ms is better.
- PageSpeed Insights (and other testing tools) only test TTFB in 1 location.
- WP Hosting Benchmark also tests hosting performance (here are my results).
- Combining a good host/CDN is arguably the best way to improve TTFB (using a host with improved specs on top of Cloudflare Enterprise hits 2 birds with 1 stone).
Mainstream hosts (like SiteGround, Hostinger, and WPX) don’t have a lot of CPU/RAM, use slower SATA SSDs, and are shared hosting with strict CPU limits which force you to upgrade plans. Cloud hosting is faster, but Kinsta still uses SATA SSDs with low CPU/RAM, PHP workers, and monthly visits (Redis also costs $100/month). Cloudways Vultr HF is who I previously used, but again, they start with only 1 CPU + 1GB RAM on slower Apache servers, PHP-FPM, and GZIP.
Here are Rocket.net’s:
All plans use 32 CPU cores + 128GB RAM with NVMe (faster than SATA), Redis (better than memcached), LiteSpeed’s PHP, and Brotli (smaller compression than GZIP). They have no PHP worker limits since only about 10% of traffic hits your origin due to their Cloudflare Enterprise.
SiteGround | Hostinger | Kinsta | Cloudways Vultr HF | Rocket.net | |
---|---|---|---|---|---|
Hosting type | Shared | Shared | Cloud | Cloud | Private cloud |
Storage | SATA | SATA | SATA | NVMe | NVMe |
CPU cores | Not listed | 1-2 | 12 | 1 | 32 |
RAM (GB) | Not listed | .768 – 1.536 | 8 | 1 | 128 |
Object cache | Memcached | x | Redis ($100/mo) | Redis (Pro) | Redis |
Server | Nginx | LiteSpeed | Nginx | Apache | Nginx |
PHP processing | FastCGI | LiteSpeed | FastCGI | FPM | LiteSpeed |
Compression | Brotli | Brotli | Brotli | GZIP | Brotli |
CPU limits | Very common | Low memory | PHP workers | Average | None |
Why you need Cloudflare Enterprise
Because you get Enterprise features like 270+ PoPs, prioritized routing, full page caching, HTTP/3, WAF, and image optimization. 3 problems with most CDNs are their small network (PoPs) and no full page caching or image optimization. For example, WP Rocket’s RocketCDN uses StackPath which was removed from cdnperf.com and doesn’t include image optimization with a mediocre Tbps speed of 65+. SiteGround’s CDN only has 14 PoPs. QUIC.cloud CDN (for LiteSpeed) and BunnyCDN are good, but they still don’t beat Cloudflare Enterprise. Sure, you can pay $5/mo for Cloudflare’s APO, but you’re still missing out on all other Enterprise features.
3 popular hosts with Cloudflare Enterprise
Rocket.net’s Cloudflare Enterprise is free, setup automatically, and uses full page caching (unlike Cloudways). And unlike Kinsta’s, Rocket.net has Argo Smart Routing (specifically good for WooCommerce sites), load balancing, and image optimization. Rocket.net CEO Ben Gabler also used to be StackPath’s Chief Product Officer and went as far as building Rocket.net’s data centers in the same locations as Cloudflare’s. And unlike both hosts, Rocket.net doesn’t limit PHP workers (there’s no CPU limits) and monthly visit limits are 10-25 times more than Kinsta’s.
Cloudflare Enterprise (Kinsta) | Cloudflare Enterprise (Cloudways) | Cloudflare Enterprise (Rocket.net) | |
---|---|---|---|
CDN PoPs | 270 | 270 | 270 |
Prioritized routing | ✓ | ✓ | ✓ |
Full page caching | ✓ | x | ✓ |
HTTP/3 | ✓ | ✓ | ✓ |
WAF | ✓ | ✓ | ✓ |
Argo smart routing | x | ✓ | ✓ |
Load balancing | x | ✓ | ✓ |
Image optimization | x | ✓ | ✓ |
Automatic configuration | x | x | ✓ |
Price | Free | $5/mo (1 domain) | Free |
Problems with mainstream hosts
I’ve written some pretty bad reviews about SiteGround’s slow TTFB, CPU limits, and why SG Optimizer does a poor job with core web vitals (they also control several Facebook Groups and threaten to sue people who write bad reviews). Hostinger writes fake reviews and is only cheap because you get less resources like CPU/RAM. Kinsta and WP Engine are way too expensive for how many resources, PHP workers, and monthly visits you get. Along with major incidents like WPX’s worldwide outage and SiteGround’s DNS getting blocked by Google for 4 days (both WPX and SiteGround denied responsibility). One thing is clear: most mainstream hosts appear to be more interested in profits than performance. Please do your own research before getting advice.
Getting started
Step 1: Create a Rocket.net account and you’ll be prompted to add a coupon. Sign up with coupon OMM1 to get your first month for $1 (renews at $30/mo or $25/mo when paying yearly). If you sign up with my coupon or affiliate links, I get a commission which I seriously appreciate.
Step 2: Request a free migration. They did this the same day and let me review my website before it was launched with no downtime. For the record, their support is better than Kinsta’s and you can reach out to Ben Gabler or his team (via phone/chat/email) if you have questions.
Step 3: Upgrade to PHP 8.1 and ask support to install Redis (they use Redis Object Cache). These are the only things I did since Cloudflare Enterprise and backups are both automatic.
Step 4: Retest your TTFB in SpeedVitals and click through your pages to see the difference. You can also search their TrustPilot profile for people mentioning “TTFB” where they’re rated 4.9/5.
I was previously on Cloudways Vultr HF which was great, but their Cloudflare Enterprise doesn’t use full page caching (yet) and is $5/mo with annoying challenge pages. Even if their Cloudflare Enterprise was identical, Rocket.net still outperforms them with better specs like more CPU/RAM, Brotli, and LiteSpeed’s PHP (plus better support, easier to use, and usually pricing). While Cloudways is a big improvement than most hosts, you’re already spending $18/mo for Vultr HF’s lowest 1 CPU plan with Cloudflare Enterprise. At that point, the extra $7/mo you’d be spending at Rocket.net is worth it. Rocket.net’s dashboard is also much easier.
For small sites on a budget, NameHero’s Turbo Cloud plan is similar to Hostinger between LiteSpeed, cPanel, and pricing. However, NameHero’s Turbo Cloud plan has about 1.5x more resources (3 CPU + 3GB RAM) with NVMe storage. NameHero’s support/uptimes are also better shown in TrustPilot reviews. This is one the fastest setups on a budget… you get a LiteSpeed server + LiteSpeed Cache + QUIC.cloud CDN, and email hosting. The main con is their data centers are only in the US and Netherlands. If these aren’t close to your visitors, make sure to setup QUIC.cloud’s CDN which has HTML caching (ideally the paid plan which uses all 70 PoPs).
Latency is also included in TTFB. Two simple ways to improve this are using a fast DNS like Cloudflare and tweaking Cloudflare SSL/TLS settings (using higher TLS versions for example).
6. Eliminate Render-Blocking CSS/JS
These contribute to “element render delay” which is 10% of LCP.
The easiest way to eliminate render-blocking resources is to view your PSI report and learn whether these files are from CSS or JavaScript (also take note of where they’re loading from).
Critical CSS loads above the fold CSS faster and most cache plugins have settings for it. You can use a critical CSS generator, but this isn’t preferred since critical CSS can be different depending on the page/post and changes if you make CSS changes where critical CSS needs to be updated.
Deferring JavaScript pushes JavaScript files into the footer so they’re loaded non render-blocking. Again, most cache plugins have a setting for this. If enabling it breaks your website, you should really try to exclude problematic files rather than disabling the setting completely.
Autoptimize and Async JavaScript are also good for handling render-blocking CSS/JS. For a deeper guide in Chrome Dev Tools, see 6:27 of Google’s video on improving load performance.
7. Use Font-Display: Optional
Fonts add delays when they’re not loaded properly which increases LCP and causes layout shifts. It’s often a tradeoff between FOIT (flash of invisible text) or FOUT (flash of unstyled text).
If you need to ensure text remains visible during webfont load, use font-display: optional which is recommended by Google for optimal performance. Most tools only support “swap” like cache plugins, Elementor, and even dedicated font plugins like OMGF and Swap Google Fonts Display. You can either just use the swap method, or use font-display: optional by editing your font’s CSS and adding the code yourself. The only plugin I know that supports optional is WP FOFT Loader.
/assets/vendor/googleapis/css2?family=Lato:wght@100&display=optional
@font-face {
font-family: "Lato Regular";
font-weight: 300;
font-style: normal;
src: url("fonts/Lato-Regular-BasicLatin.woff2") format("woff2");
font-display: optional;
}
8. Reduce Font Requests And File Sizes
LCP is the load time of your main content which fonts are part of.
Font Optimization 101
- Use WOFF/WOFF2, not TTF.
- Consolidate font families, weights, icons.
- Disable font icons if you’re not using them.
- Host fonts locally (instead of fonts.gstatic.com).
- If they load from fonts.gstatic.com, preconnect that domain.
- Once hosted locally, preload important font files loading above the fold.
- Inline fonts (some cache plugins do this or use Elementor’s inline experiment).
9. Lazy Render HTML Elements
FlyingPress and LiteSpeed Cache can lazy render HTML elements.
This is similar to lazy loading images but can be done for any element on your website (#comments and #footer are common, just make sure to copy selectors for your own site as shown in the video). It improves LCP by letting browsers focus more on above the fold content.
10. Preload, Preconnect, Prefetch
Other than prioritizing above the fold images, there may be other files you can prioritize with resource hints. This can be done in most optimization plugins or by adding code to your head.
The “avoid changing critical requests” section of PSI shows resources loaded with a high priority. You should also consider preloading self-hosted fonts and CSS/JS files needed for above the fold content. Just make sure you test your results (in your Waterfall chart) after adding each resource hint. Too many hints or not using them correctly can hurt performance.
Preload – can also be done with above the fold fonts, CSS, JS, and other files types. For example, you could preload the WordPress Block Library stylesheet. Fonts should use the crossorigin attribute. As with all resource hints, test performance after each hint is added.
<link rel="preload' href="/style.css" as="style">
<link rel="preload' href="/script.js" as="script">
<link rel="preload' href="/font.woff2" as="font" crossorigin>
Preconnect – usually only done with CDN URLs (i.e. BunnyCDN) and third-party fonts (i.e. fonts.gstatic.com). Cloudflare doesn’t use a CDN URL and most cache plugins automatically preconnect the CDN URL when you add it to the plugin settings. Since fonts should be hosted locally and CDN URLs are preconnected by cache plugins, there’s usually no need to do this.
<link rel="preconnect" href="/assets/vendor/gstatic" crossorigin>
<link rel="preconnect" href="https://cdn.yourdomain.com" crossorigin>
Prefetch – usually nothing to do here unless you have third-party code loading above the fold, like a social sharing plugin loading at the top of your blog making requests to Facebook. Third-party code should be delayed when it’s loaded below the fold instead of using the prefetch hint.
<link rel="dns-prefetch" href="https://connect.facebook.net">
11. Optimize Images
While above the fold images are the most important to optimize largest contentful paint, all images are obviously important. Most of these are recommendations in PageSpeed Insights.
I prefer image CDNs like Cloudflare Mirage + Polish (what I use with Cloudflare Enterprise) or Bunny Optimizer which eliminates the need for image optimization plugins and are automatic.
- Serve smaller Images to mobile – Cloudflare’s image resizing and Bunny Optimizer resize images for mobile while other CDNs like RocketCDN do not. Or you can use ShortPixel Adaptive Images. This can improve your mobile LCP score.
- Properly size images – crop/resize images to their correct dimensions.
- Compress images – Lighthouse tests images at 85%, so that’s a good number.
- Specify image dimensions – most cache plugins have a setting to add missing image dimensions. Otherwise, you can manually add a width/height attribute to the image’s HTML which makes the image load faster and prevents layout shifts.
- Use WebP – faster image format supported by most image CDN/plugins. You could even use a WebP converter to only convert above the fold images if you don’t want to make the full switch yet. If you’re not using WebP, know when to use jpg or png.
12. Use Brotli When Possible
Brotli compresses files to smaller sizes than GZIP. The trick is finding a host that supports it, for example, Rocket.net and Kinsta do. Check with your host and consider this next time you move.
13. Increase Cache Expiration Time
Longer cache expirations prevent the server from rebuilding the cache as frequently and improves LCP with better cache hit ratios. Google also suggests this in a YouTube video on LCP.
If using Cloudflare, you can do this under browser cache TTL in the Caching settings. Google recommends 1 year to fix “serve static assets with an efficient cache policy”. This is good for static sites (like my blog) but WooCommerce and dynamic sites should only use about 1 month.
14. Choose The Right Cache Plugin And Settings
Again, while I try to keep things unbiased, FlyingPress is clearly better at optimizing LCP than WP Rocket and SiteGround Optimizer. Gijo is usually the first to release new features which address core web vitals like delaying JavaScript or adding fetchpriority. Sometimes WP Rocket follows, but other times they don’t add a feature at all. SiteGround Optimizer is far behind both and primarily optimizes for caching instead of core web vitals (with lots of compatibility issues).
WP Rocket has no image optimization, their CDN has no features other than serving files, no documented APO compatibility (still), and way too many lacking features to keep paying for it.
Use FlyingPress or LiteSpeed Cache, not WP Rocket or SiteGround Optimizer.
I have tutorials for nearly every cache plugin.
LCP Optimization | SG Optimizer | WP Rocket | FlyingPress |
---|---|---|---|
Preload critical images | x | x | ✓ |
Exclude leading images | x | x | ✓ |
Fetchpriority resource hint | x | x | ✓ |
Remove unused CSS | x | Inline | Separate file |
Critical CSS | x | ✓ | ✓ |
Font-display: swap | x | ✓ | ✓ |
Lazy render HTML elements | x | x | ✓ |
Documented APO compatibility | x | x | ✓ |
CDN | SiteGround CDN | StackPath | BunnyCDN |
Image optimization via CDN | x | x | ✓ |
Serve small images to mobile via CDN | x | x | ✓ |
15. Enable Signed Exchanges (SXGs) In Cloudflare
Signed Exchanges improve largest contentful paint when people click your links in Google’s search results (through prefetching). Google lists Cloudflare in their documentation and says enabling it can lead to a substantial improvement. This is found under Speed → Optimization.
16. Use Cloudflare Workers For Serverless Rendering
Philip Walton was able to reduce LCP by about 80% using service workers.
Cloudflare has documentation on deploying a static WordPress site which is mainly for developers (which I don’t consider myself one), but I’ll leave it here in case you want to try it.
I’m a blogger, I know my limits :/
17. Move Plugin Content, Ads, And Animations Below The Fold
I want to emphasize that large, unoptimized files loading above the fold increases LCP.
Loading Google AdSense in your header, heavy image galleries or animations at the top of content, mega menus, and social sharing plugins at the top of your blog is usually not a good idea. Sure, you may be able to optimize them, but if you can’t and they’re killing your LCP or other scores, try moving them below the fold so they can be delayed or optimized other ways.
How do I improve largest contentful paint in WordPress?
LCP can be improved by optimizing above the fold content, eliminating delays, and reducing/optimizing files and TTFB. Since LCP measures the load time of main content in the viewport, there are many factors.
How do I improve largest contentful paint using WP Rocket?
WP Rocket optimizes LCP with features like critical CSS, font-display swap, and removing unused CSS. However, it lacks LCP optimizations like automating the optimization of above the fold images, fetchpriority hints, and serving smaller images to mobile devices. These features have already been added in other cache plugins or their CDNs, not in WP Rocket.
Cheers,
Tom