Я Максим, веб-разработчик, и с марта 2024 года Google официально заменил метрику FID на INP в Core Web Vitals. Для Яндекса показатели Core Web Vitals тоже имеют значение — они учитываются как фактор ранжирования. Если ваш сайт медленно реагирует на клики и нажатия — это бьёт не только по пользовательскому опыту, но и по позициям в поиске. Давайте разберёмся, что такое INP, почему она важнее старой FID и как конкретно оптимизировать эту метрику на вашем сайте.

Что измеряет INP и чем она отличается от FID

INP (Interaction to Next Paint) измеряет время от действия пользователя — клика, нажатия клавиши, тапа по экрану — до момента, когда браузер визуально отреагирует на это действие. Нажали кнопку «Добавить в корзину» — и через сколько миллисекунд вы увидите, что кнопка нажалась, появилось уведомление, изменился счётчик товаров? Это и есть INP.

Старая метрика FID (First Input Delay) измеряла только задержку самого первого взаимодействия на странице. Пользователь зашёл на сайт, впервые кликнул по чему-то — FID фиксировала, сколько прошло до начала обработки этого клика. Но только первого. Все последующие взаимодействия FID полностью игнорировала. А ведь именно в процессе работы со страницей — при фильтрации товаров, переключении табов, открытии модалок — возникают самые заметные тормоза.

INP решает эту проблему. Она фиксирует все взаимодействия за сессию пользователя и выбирает наихудшее (с поправкой: если взаимодействий больше 50, метрика берёт 98-й перцентиль, а не абсолютный максимум). Таким образом, INP отражает реальную отзывчивость сайта в течение всего визита, а не только первую секунду.

На практике разница между FID и INP огромна. Я видел сайты с отличным FID (50 мс), но ужасным INP (600+ мс). Первый клик обрабатывался быстро, потому что при загрузке страницы основной поток ещё не был забит задачами. Но после загрузки всех скриптов, инициализации виджетов и аналитики — каждый последующий клик тормозил.

Какие значения INP считаются приемлемыми

Google определяет три порога. Хорошо — менее 200 миллисекунд. Нужна доработка — от 200 до 500 миллисекунд. Плохо — более 500 миллисекунд. Цель — попасть в зелёную зону, ниже 200 мс. Это значит, что подавляющее большинство взаимодействий пользователя с сайтом обрабатываются визуально менее чем за 200 мс — на уровне, который ощущается как «мгновенный» отклик.

Для понимания масштаба: 200 мс — это примерно время моргания глаза. Человек физически не успевает осознать задержку. При 500 мс задержка уже заметна — пользователь чувствует, что «сайт тормозит», даже если не может объяснить, в чём конкретно проблема. При 1000+ мс впечатление «сломанного» интерфейса — люди начинают кликать повторно, что часто создаёт ещё больше проблем.

Три фазы INP: что именно тормозит

Каждое взаимодействие в браузере проходит три фазы, и INP — это сумма времени всех трёх. Понимание этих фаз критически важно для оптимизации, потому что причина тормозов может быть в любой из них.

Фаза 1: Input Delay (задержка ввода). Время от момента, когда пользователь кликнул, до момента, когда браузер начал выполнять обработчик события (event handler). Задержка возникает, когда основной поток (main thread) занят другой задачей. Представьте: пользователь нажимает кнопку, но браузер в этот момент выполняет сложный скрипт аналитики или пересчитывает CSS-анимацию. Клик встаёт в очередь и ждёт, пока основной поток освободится.

Фаза 2: Processing Time (время обработки). Время выполнения самого обработчика события — вашего JavaScript-кода, который запускается в ответ на клик. Если обработчик делает сложные вычисления, обращается к DOM, запускает цепочку обновлений состояния — это время растёт.

Фаза 3: Presentation Delay (задержка отрисовки). Время от завершения обработчика до момента, когда браузер фактически нарисовал обновлённый кадр на экране. Это включает пересчёт стилей, layout, paint и composite — все этапы рендеринга.

Оптимизируя INP, нужно разбираться, какая именно фаза является узким местом. В Chrome DevTools это можно увидеть в панели Performance — каждое взаимодействие показывает разбивку по фазам.

Почему INP может быть плохим: типичные причины

Тяжёлый JavaScript и блокировка основного потока

Самая частая причина плохого INP — длинные задачи (Long Tasks) в основном потоке. Основной поток в браузере — один. Он обрабатывает и JavaScript, и пользовательский ввод, и рендеринг. Когда JavaScript-функция выполняется 300 мс подряд — весь этот период браузер не может обработать ни один клик пользователя. Клик встаёт в очередь, и пользователь видит «зависание».

Я часто вижу это на сайтах с тяжёлыми фреймворками. React-приложение, которое при каждом обновлении состояния пересчитывает и перерисовывает сотни DOM-элементов — типичный сценарий. Или SPA (Single Page Application), где переключение маршрута запускает загрузку и парсинг огромного бандла JavaScript.

Избыточные обработчики событий

Когда на каждый элемент страницы навешен обработчик клика, hover, scroll — суммарная нагрузка на основной поток возрастает. Особенно проблематичны обработчики скролла, которые срабатывают десятки раз в секунду и запускают пересчёт позиций, анимации, ленивую загрузку.

Сторонние скрипты

Аналитика (Яндекс Метрика, Google Analytics), онлайн-чаты (Jivo, Carrot quest), рекламные пиксели, виджеты соцсетей — каждый из них загружает свой JavaScript и периодически выполняет задачи в основном потоке. По отдельности каждый скрипт может быть лёгким. Но когда их пять-семь — суммарная нагрузка становится серьёзной, и любой клик пользователя рискует «попасть» в момент, когда основной поток занят одним из этих скриптов.

Я проводил аудит для клиента, у которого на странице было подключено восемь сторонних скриптов. После удаления четырёх ненужных (два устаревших пикселя, неиспользуемый виджет и дублирующий скрипт аналитики) INP улучшился с 480 мс до 190 мс — без единой строчки оптимизации собственного кода.

Сложные CSS-перерисовки после взаимодействия

Если после клика браузеру нужно пересчитать layout (расположение элементов на странице) для большого количества элементов — фаза Presentation Delay растёт. Это происходит, когда клик изменяет размеры элемента, который влияет на расположение сотен других элементов. Например, открытие аккордеона, которое сдвигает весь контент страницы, или фильтрация товаров с перестроением сетки.

Практические способы оптимизации INP

Разбивайте длинные задачи (yield to main thread)

Если у вас есть JavaScript-функция, которая работает 300+ мс — разбейте её на части. Между частями дайте браузеру возможность обработать пользовательский ввод. В современных браузерах есть API scheduler.yield() — он делает именно это. Для совместимости со старыми браузерами используйте паттерн с setTimeout(0) или requestAnimationFrame.

Как это выглядит на практике: вместо одного цикла, который обрабатывает 1000 элементов за раз, разбиваете его на пакеты по 50 элементов с промежутком для обработки ввода. Пользователь не заметит разницы в скорости выполнения, но сайт перестанет «зависать» при кликах.

Используйте debounce и throttle

Для обработчиков событий, которые срабатывают часто — скролл, ресайз, ввод текста — ограничивайте частоту вызовов. Debounce вызывает функцию только после паузы (например, через 300 мс после последнего нажатия клавиши). Throttle — не чаще чем раз в заданный интервал (например, раз в 100 мс). Это стандартные приёмы, но их удивительно часто забывают.

Ленивая загрузка JavaScript

Не грузите весь JavaScript при старте. Используйте динамический import() для загрузки модулей по мере необходимости. В React — это React.lazy и Suspense. В Next.js — dynamic imports. Код модального окна не нужен, пока пользователь не нажал кнопку — загружайте его в момент нажатия.

Это снижает и Input Delay (меньше кода в основном потоке), и время начальной загрузки (меньше JavaScript для парсинга и компиляции).

Оптимизируйте сторонние скрипты

Загружайте аналитику и виджеты асинхронно — с атрибутом async или defer. Ещё лучше — загружайте их через requestIdleCallback или через IntersectionObserver (подгружать чат-виджет, только когда пользователь проскроллил до определённого места). Удалите неиспользуемые скрипты — каждый из них ест ресурсы.

Для Яндекс Метрики и аналогичных счётчиков — используйте загрузку с задержкой: подключайте скрипт через setTimeout с задержкой в две-три секунды после загрузки страницы. К этому моменту основной контент уже отрисован, и скрипт аналитики не помешает первым взаимодействиям.

Минимизируйте DOM и используйте виртуализацию

Чем меньше DOM-элементов на странице — тем быстрее браузер выполняет пересчёт стилей и layout после каждого взаимодействия. Если у вас список из 500 товаров — не рендерите их все. Используйте виртуализацию (react-window, react-virtualized, TanStack Virtual): рендерится только то, что видно в viewport, остальное создаётся при скролле. Это драматически снижает Presentation Delay.

Используйте CSS-свойство contain

CSS-свойство contain: layout (или contain: content) говорит браузеру, что изменения внутри этого элемента не влияют на расположение элементов снаружи. Это позволяет браузеру ограничить пересчёт layout областью одного контейнера, а не всей страницы. Для карточек товаров, элементов списка, блоков контента — это простой способ ускорить отрисовку.

Переносите вычисления в Web Workers

Если у вас есть тяжёлые вычисления (сортировка больших массивов, парсинг данных, обработка изображений) — перенесите их в Web Worker. Web Worker выполняется в отдельном потоке и не блокирует основной. Результат вычисления передаётся обратно через postMessage. Основной поток остаётся свободным для обработки пользовательского ввода.

Как проверить и отслеживать INP

Для разовой проверки используйте PageSpeed Insights — он показывает INP в разделе Core Web Vitals, причём как лабораторные данные, так и полевые (от реальных пользователей, если сайт достаточно посещаемый). Chrome DevTools — вкладка Performance — показывает все взаимодействия и длинные задачи. Web Vitals Extension для Chrome отображает INP в реальном времени прямо на странице — удобно для тестирования.

Для постоянного мониторинга подключите web-vitals JavaScript-библиотеку — она отправляет данные о реальном INP пользователей в вашу аналитику. Это важнее лабораторных тестов, потому что INP зависит от устройства пользователя: на мощном MacBook Pro разработчика всё летает, а на бюджетном Android-смартфоне клиента — тормозит.

В Яндекс Вебмастере также можно посмотреть отчёт по Core Web Vitals вашего сайта — там видны проблемные страницы, на которых стоит сосредоточить усилия.

INP и Яндекс: имеет ли значение

Google создал метрику INP, но Яндекс тоже учитывает отзывчивость сайта при ранжировании. Яндекс использует собственные поведенческие метрики, но суть та же: если пользователь кликает и ничего не происходит — это негативный сигнал. Плохая отзывчивость ведёт к отказам, коротким сессиям, возврату в поиск — а это прямые поведенческие факторы, которые Яндекс учитывает.

Оптимизируя INP, вы улучшаете реальный пользовательский опыт — а значит, улучшаете поведенческие факторы и для Яндекса, и для Google одновременно.

Итого

INP — метрика, которая отражает то, что чувствует реальный пользователь: насколько быстро сайт реагирует на его действия. Это не абстрактный технический показатель, а ощущение отзывчивости, которое влияет на конверсию, на лояльность и на позиции в поиске.

Главные инструменты оптимизации: разбивать длинные задачи в основном потоке, лениво загружать JavaScript, оптимизировать сторонние скрипты, минимизировать DOM, использовать виртуализацию и CSS contain. Начните с аудита в Chrome DevTools — найдите самые длинные задачи и устраните их, а затем подключите мониторинг через web-vitals, чтобы отслеживать INP на реальных пользователях.