# Баннеры cookie и Core Web Vitals: как удержать LCP, CLS и INP в норме

> Как баннеры cookie ухудшают LCP, CLS и INP и как это исправить: асинхронная загрузка, отсутствие сдвигов макета, отложенный центр настроек и легкие обработчики.

Source: https://www.cookiesh.eu/ru/blog/cookie-banners-core-web-vitals  
Published: 2026-07-30

## Key takeaways

- Баннер cookie может влиять на все три метрики Core Web Vitals: LCP, CLS и INP.
- Загружайте скрипт согласия асинхронно и держите необязательные теги неактивными, чтобы баннер никогда не блокировал отрисовку основного контента.
- Показывайте баннер как фиксированный оверлей или резервируйте под него место, чтобы он никогда не сдвигал содержимое страницы.
- Делайте обработчики кнопок «Принять» и «Отклонить» легкими: сначала обновите интерфейс, затем уступите основной поток и только потом загружайте теги.
- Тестируйте в новом сеансе из региона, где показывается баннер, ведь именно тогда проявляется его влияние на производительность.

Баннер cookie может ухудшить все три метрики Core Web Vitals: он может задержать отрисовку самого крупного элемента (Largest Contentful Paint, LCP) или сам стать им, сдвигать содержимое и повышать совокупный сдвиг макета (Cumulative Layout Shift, CLS), а также делать кнопку «Принять» медлительной, что отражается на задержке до следующей отрисовки (Interaction to Next Paint, INP). Способы исправления известны: загружайте скрипт согласия асинхронно, показывайте баннер как фиксированный оверлей, откладывайте второстепенный интерфейс и делайте обработчики кликов легкими.

## Почему баннеры cookie влияют на Core Web Vitals?

Баннер часто оказывается первым, что видит новый посетитель, и состоит он из JavaScript, CSS и текста, которые конкурируют с вашим основным контентом за пропускную способность и время основного потока. Core Web Vitals измеряют именно эту конкуренцию, причем оценка ведется по 75-му процентилю реальных загрузок страниц.

| Метрика | Что она измеряет | Порог «хорошо» | Как баннер может ее ухудшить |
| --- | --- | --- | --- |
| LCP | Момент отрисовки самого крупного изображения или текстового блока | 2,5 с или меньше | Скрипт согласия, блокирующий отрисовку, или сам баннер, ставший самым крупным элементом |
| CLS | Насколько сильно видимое содержимое неожиданно смещается | 0,1 или меньше | Баннер, вставленный в поток страницы и сдвигающий содержимое вниз |
| INP | Насколько быстро страница реагирует на клики, касания и нажатия клавиш | 200 мс или меньше | Тяжелая работа в обработчике кнопки «Принять» или «Отклонить» |

В марте 2024 года INP заменил метрику First Input Delay (FID), и для согласия это важно. FID измерял только задержку перед обработкой первого взаимодействия; INP измеряет полное время от любого взаимодействия до следующего кадра, а «Принять все» часто становится первым, на что нажимает посетитель.

## Как не дать скрипту согласия заблокировать LCP?

Загружайте его с атрибутом `async` и делайте его компактным. Синхронный скрипт в `<head>` останавливает парсер HTML, пока не загрузится и не выполнится, а это задерживает заголовок и главное изображение вместе со всем остальным.

```html
<head>
  <script src="https://consent.example.com/loader.js" async></script>

  <!-- Неактивен, пока скрипт согласия не включит его после получения согласия -->
  <script type="text/plain" data-consent="analytics"
          src="https://analytics.example.com/script.js"></script>
</head>
```

Асинхронная загрузка безопасна, если необязательные теги неактивны, как в этом примере: ничего не выполняется, пока скрипт согласия этого не разрешит. Подходы с «автоблокировкой», которые перехватывают скрипты по мере их добавления, обычно должны выполняться синхронно раньше всех остальных скриптов, а это стоит времени отрисовки. Методы сравниваются в нашем руководстве о том, [как блокировать скрипты до получения согласия](/ru/blog/block-scripts-until-consent).

Вторая ловушка для LCP — сам баннер. LCP фиксирует самое крупное изображение или текстовый блок, отрисованный в области просмотра до взаимодействия посетителя со страницей. На небольшом телефоне баннер с длинным абзацем может оказаться больше вашего заголовка, и если он отрисовывается поздно, поздно наступает и LCP. Делайте текст первого уровня лаконичным, используйте системный шрифт, чтобы баннер никогда не ждал загрузки веб-шрифта, и никогда не выводите баннер в виде изображения.

Откладывать показ баннера бесполезно: поздний баннер все равно может стать элементом LCP, просто позже.

## Как не дать баннеру вызывать сдвиги макета?

Показывайте его как фиксированный оверлей. CLS учитывает смещение уже существующего содержимого, поэтому элемент с `position: fixed`, появляющийся поверх страницы, ничего не сдвигает. Классическая ошибка — панель, вставляемая в начало `<body>` после первой отрисовки, которая сдвигает вниз всю страницу.

```css
.consent-banner {
  position: fixed;
  inset: auto 0 0 0; /* закреплен внизу, вне потока документа */
  z-index: 1000;
  font: 1rem/1.5 system-ui, sans-serif; /* не нужно ждать веб-шрифт */
  animation: consent-in 200ms ease-out;
}

@keyframes consent-in {
  from { transform: translateY(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .consent-banner { animation: none; }
}
```

Если используете анимацию, анимируйте `transform` или `opacity`. Анимация `top`, `height` или `margin` меняет макет и может засчитываться как сдвиг. Если дизайн действительно требует баннера в потоке документа, резервируйте под него место в HTML, отрисованном на сервере, — но это хорошо работает, только если сервер считывает файл cookie согласия и не резервирует место для вернувшихся посетителей.

Продумайте и то, что происходит после получения согласия. Сдвиги в течение 500 мс после клика или нажатия клавиши не учитываются в CLS, а вот рекламный блок, встроенное видео или виджет чата, загружающиеся через несколько секунд, учитываются. Задайте таким контейнерам фиксированные размеры или `aspect-ratio`.

## Как отложить интерфейс баннера, не нарушая требований?

Отдавайте первый уровень сразу, а центр настроек загружайте по требованию. Первый уровень — это короткое сообщение и несколько кнопок; второй уровень с переключателями категорий, списками поставщиков и таблицами файлов cookie обычно и составляет основной вес.

Откладывать нельзя сам выбор. Кнопке «Отклонить все» место на первом уровне, причем с той же заметностью, что и у «Принять все». В декабре 2021 года французский регулятор CNIL оштрафовал Google на 150 млн евро, а Facebook — на 60 млн евро, потому что отказаться от файлов cookie было сложнее, чем принять их. Подробнее читайте в статьях [темные паттерны в баннерах cookie](/ru/blog/cookie-banner-dark-patterns) и [лучшие практики дизайна баннеров](/ru/blog/cookie-banner-design-best-practices).

## Как сохранить отзывчивость кнопок «Принять» и «Отклонить» для INP?

Делайте минимум до следующей отрисовки, а затем уступайте поток. Медленный обработчик обычно в рамках одной длинной задачи записывает файл cookie согласия, отправляет запись в журнал согласий, обновляет Google Consent Mode и внедряет несколько скриптов поставщиков, поэтому кнопка выглядит зависшей.

```js
function yieldToMain() {
  if (globalThis.scheduler?.yield) return globalThis.scheduler.yield();
  return new Promise((resolve) => setTimeout(resolve, 0));
}

acceptButton.addEventListener('click', async () => {
  banner.remove();                                    // 1. сначала видимая реакция
  saveConsent({ analytics: true, marketing: true });  // 2. быстро и синхронно
  await yieldToMain();                                // 3. даем браузеру отрисовать кадр
  activateTags(['analytics', 'marketing']);           // 4. тяжелая работа в следующей задаче
});

customizeButton.addEventListener('click', async () => {
  customizeButton.setAttribute('aria-busy', 'true');
  const { openPreferences } = await import('./preference-center.js'); // загружается по требованию
  openPreferences();
});
```

Отправляйте запись в журнал согласий с помощью `navigator.sendBeacon()`, чтобы сетевые операции никогда не задерживали взаимодействие, а большое количество тегов активируйте пакетами, уступая поток между ними. `scheduler.yield()` пока поддерживается не во всех браузерах, поэтому нужен запасной вариант.

## Как протестировать влияние баннера?

Тестируйте сначала как новый посетитель, а затем как вернувшийся. Лабораторные инструменты вроде Lighthouse запускаются с пустым хранилищем, поэтому всегда видят баннер:

1. Откройте страницу в новом профиле браузера из региона, где показывается баннер.
2. Запустите Lighthouse или PageSpeed Insights и проверьте, какой элемент определен как элемент LCP.
3. Запишите трассировку на панели Performance в Chrome DevTools, нажмите «Принять все» и поищите длинные задачи после клика.
4. В той же трассировке проверьте сдвиги макета во время появления баннера и после загрузки тегов.
5. Повторите тест как вернувшийся посетитель с сохраненным согласием, ведь в этом случае срабатывает больше тегов.
6. Затем сравните полевые данные в Search Console или PageSpeed Insights; они охватывают скользящее окно в 28 дней, поэтому изменения проявляются постепенно.

## Итоги

Баннер согласия не обязан ухудшать Core Web Vitals. Загружайте его асинхронно, держите вне потока документа, откладывайте тяжелый второй уровень и делайте обработчики кликов легкими, сохраняя при этом одинаковую простоту всех вариантов выбора. Такие инструменты, как Cookiesh, могут взять на себя загрузку: асинхронный загрузчик весит меньше 5 КБ в сжатом gzip виде, раздается через глобальную граничную CDN и спроектирован так, чтобы не вызывать сдвигов макета.

*Эта статья носит общий информационный характер и не является юридической консультацией. Для решений, касающихся вашей конкретной ситуации, обратитесь к квалифицированному специалисту по защите данных.*

## FAQ

### Улучшит ли Core Web Vitals скрытие баннера от Lighthouse?

Нет. Оценка Core Web Vitals в Google основана на полевых данных реальных пользователей Chrome, многие из которых видят ваш баннер. Скрывая его от лабораторных инструментов, вы скрываете проблему только от себя, а если отдавать тестовым инструментам другую страницу, диагностика становится ненадежной.

### Что лучше для производительности: панель внизу экрана или модальное окно по центру?

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

### Стоит ли отдельно измерять Core Web Vitals для посетителей, которые уже дали согласие?

Это полезно. Вернувшиеся посетители не видят баннер, но у них срабатывает больше тегов, поэтому их профиль загрузки и отзывчивости отличается от профиля новых посетителей. Сегментация измерений покажет, какая группа требует доработки, но помните, что отправка данных мониторинга реальных пользователей третьей стороне сама по себе может требовать согласия.

## Sources

- [web.dev: Web Vitals](https://web.dev/articles/vitals)
- [Directive 2002/58/EC (ePrivacy Directive), EUR-Lex](https://eur-lex.europa.eu/eli/dir/2002/58/oj)
- [EDPB Guidelines 05/2020 on consent](https://www.edpb.europa.eu/our-work-tools/our-documents/guidelines/guidelines-052020-consent-under-regulation-2016679_en)
