---
title: CSS для Web Vitals
subhead: Методы оптимизации Web Vitals, связанные с CSS
authors:
  - katiehempenius
  - una
date: 2021-06-02
hero: image/j2RDdG43oidUy6AL6LovThjeX9c2/uq7JQlKJo7KBETXnVuTf.jpg
alt: Многоцветный градиент
description: В этой статье рассказывается о методах оптимизации Web Vitals, связанных с CSS.
tags:
  - blog
  - performance
  - css
---

Приемы, используемые при написании стилей и создании макетов, могут значительно влиять на метрики [Core Web Vitals](/learn-core-web-vitals/). Это особенно справедливо для метрик [Cumulative Layout Shift (CLS)](/cls) (Совокупное смещение макета) и [Largest Contentful Paint (LCP)](/lcp) (Отображение самого крупного элемента содержимого).

В этой статье рассказывается о методах оптимизации Web Vitals, связанных с CSS. Эти методы разделены на группы по различным аспектам страниц: макетам, изображениям, шрифтам, анимации и загрузке. Попутно мы расскажем, как улучшить следующий [пример страницы](https://codepen.io/una/pen/vYyLKvY):

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/pgmpMOmweK7BVBsVkQ5g.png", alt="Снимок экрана с примером сайта", width="800", height="646" %}

## Макет

### Вставка контента в DOM

При добавлении контента на страницу после того как окружающий контент уже загружен, содержимое страницы сдвигается вниз. Это приводит к [сдвигам макета](/cls/#layout-shifts-in-detail).

Распространенный пример такой проблемы — [уведомления о файлах cookie](/cookie-notice-best-practices/) (особенно размещенные в верхней части страницы). Среди прочих элементов страницы, которые часто приводят к таким сдвигам макета при загрузке, — рекламные объявления и внедренные элементы.

#### Выявление проблемы

С помощью аудита Avoid large layout shifts в в Lighthouse можно выявить сдвинутые элементы страницы. Для нашей демонстрации результаты выглядят следующим образом:

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/jaHtgwzDXCjx3vAFOO33.png", alt="Аудит Avoid large layout shifts в Lighthouse", width="800", height="500" %}

В этих результатах не указано уведомление о файлах cookie, так как оно не сдвигается при загрузке. Тем не менее при его отображении смещаются расположенные под ним элементы (то есть `div.hero` и `article`) на странице. Дополнительные сведения о выявлении сдвигов макета и их устранении см. в статье «[Устранение сдвигов макета](/debugging-layout-shifts)».

{% Aside %}

Lighthouse анализирует производительность страницы только до события загрузки страницы. Баннеры с уведомлениями о файлах cookie, рекламные объявления и другие виджеты иногда не загружаются до тех пор, пока не будет загружена сама страница. Эти сдвиги макета также доставляют неудобства пользователям, даже если Lighthouse не помечает их.

{% endAside %}

#### Решение проблемы

Разместите уведомление о файлах cookie в нижней части страницы, используя абсолютное или фиксированное позиционирование.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/YBYLT9jJ9AXrbsaRNVoa.png", alt="Уведомление о файлах cookie, отображаемое в нижней части страницы", width="800", height="656" %}

Было:

```css
.banner {
  position: sticky;
  top: 0;
}
```

Стало:

```css
.banner {
  position: fixed;
  bottom: 0;
}
```

Другой способ предотвратить смещение макета — зарезервировать место для уведомления о файлах cookie в верхней части экрана. Это тоже эффективный подход. Дополнительные сведения см. в статье «[Рекомендации по уведомлениям о файлах cookie](/cookie-notice-best-practices/)».

{% Aside %}

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

{% endAside %}

## Изображения

### Изображения и метрика Largest Contentful Paint (LCP)

Обычно изображения — самые крупные отображаемые элементы содержимого на странице. Перечень других [элементов страницы, которые могут быть самыми крупными отображаемыми элементами содержимого](/lcp/#what-elements-are-considered), включает блоки текста и изображения элементов poster для видео. Метрика LCP зависит от времени загрузки самого крупного отображаемого элемента содержимого.

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

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/bMoAoohyLOgTqV6B7lHr.png", alt="Схема, на которой выделен самый крупный отображаемый элемент страницы в различных сценариях.", width="800", height="498" %}

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

#### Решение проблемы

Измените элемент CSS `.banner` и используйте градиент CSS, а не изображение.

Было:

```css
background: url("https://cdn.pixabay.com/photo/2015/07/15/06/14/gradient-845701\_960\_720.jpg")
```

Стало:

```css
background: linear-gradient(135deg, #fbc6ff 20%, #bdfff9 90%);
```

### Изображения и сдвиги макета

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

{% Aside %} Сдвиги макета при отображении изображений особенно заметны, если изображения загружаются медленно, например при низкоскоростном соединении или при загрузке изображения с особенно большим размером файла. {% endAside %}

#### Выявление проблемы

Выявить изображения без явно заданных атрибутов `width` и `height` можно с помощью аудита Image elements have explicit width and height в Lighthouse.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/wDGRVi7JaUOTjD9ODOk9.png", alt="Аудит Image elements have explicit width and height в Lighthouse", width="800", height="274" %}

В этом примере и у главного изображения, и у изображения статьи отсутствуют атрибуты `width` и `height`.

#### Решение проблемы

Чтобы не допустить сдвиги макета, настройте атрибуты `width` и `height` для этих изображений.

Было:

```html
<img src="https://source.unsplash.com/random/2000x600" alt="Изображение, которое необходимо загрузить">
<img src="https://source.unsplash.com/random/800x600" alt="Изображение, которое необходимо загрузить">
```

Стало:

```html
<img src="https://source.unsplash.com/random/2000x600" width="2000" height="600" alt="Изображение, которое необходимо загрузить">
<img src="https://source.unsplash.com/random/800x600" width="800" height="600" alt="Изображение, которое необходимо загрузить">
```

<figure>{% Video src="video/j2RDdG43oidUy6AL6LovThjeX9c2/fLUscMGOlGhKnNHef2py.mp4" %} <figcaption> Теперь загрузка изображения не приводит к сдвигу макета. </figcaption></figure>

{% Aside %} Другой подход к загрузке изображений — использовать атрибуты [`srcset`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/srcset) и [`sizes`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement/sizes) и указать значения для атрибутов `width` и `height`. Это повысит производительность и позволит передавать изображения разного размера на разные устройства. Дополнительные сведения см. в статье «[Передача адаптивных изображений](/serve-responsive-images/)». {% endAside %}

## Шрифты

Шрифты могут задерживать рендеринг текста и приводить к сдвигам макета. Таким образом, важно быстро доставлять их.

### Отложенный рендеринг текста

По умолчанию браузер не сразу отображает элемент text, если связанные с ним веб-шрифты еще не загружены. Это сделано, чтобы предотвратить [«мигание текста без стиля« (FOUT)](https://en.wikipedia.org/wiki/Flash_of_unstyled_content). Во многих ситуациях это приводит к задержке [первого отображения содержимого (First Contentful Paint [FCP])](/fcp), а в некоторых ситуациях — к задержке при отображении самого крупного элемента содержимого (Largest Contentful Paint [LCP]).

{% Aside %}

По умолчанию Firefox и браузеры на основе Chromium [блокируют рендеринг текста на время до 3 секунд](https://developers.google.com/web/updates/2016/02/font-display), если связанный с этим текстом веб-шрифт не загружен; Safari блокирует рендеринг текста на неопределенное время. [Период блокировки](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display#the_font_display_timeline) начинается, когда браузер запрашивает веб-шрифт. Если к концу периода блокировки шрифт все еще не загружен, браузер отображает текст с использованием резервного шрифта и заменяет этот шрифт веб-шрифтом, когда последний становится доступным.

{% endAside %}

### Сдвиги макета

Метод с заменой шрифта отлично подходит, если нужно быстро отображать содержимое для пользователя, но может привести к сдвигу макета. Такие сдвиги макета возникают, когда веб-шрифт и используемый вместо него резервный шрифт занимают разное место на странице. Используя шрифты с похожими пропорциями, можно свести к минимуму сдвиги макета.

<figure>{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/g0892nhvz3SnSaasaO1b.png", alt="Схема, на которой показан сдвиг макета, вызванный заменой шрифта", width="800", height="452" %} <figcaption> В этом примере замена шрифта привела к сдвигу элементов страницы на пять пикселей вверх. </figcaption></figure>

#### Выявление проблемы

Чтобы посмотреть, какие шрифты загружаются на определенной странице, в Devtools откройте вкладку **Network** (Сеть) и выполните фильтрацию по полю **Font** (Шрифт). Файлы шрифтов могут иметь большой размер, поэтому для повышения производительности, как правило, лучше использовать меньшее количество шрифтов.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/Ts38bQtR6x0SDgufA9vz.png", alt="Снимок экрана с шрифтом, отображаемым в DevTools", width="800", height="252" %}

Узнать, сколько времени требуется на запрос шрифта, можно на вкладке **Timing** (Время). Чем раньше будет запрошен шрифт, тем скорее он будет загружен и использован.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/wfS7qVThKMkGA7SHd439.png", alt="Снимок экрана , на котором показана вкладка Timing (Время) в DevTools", width="800", height="340" %}

Посмотреть цепочку запросов на шрифт можно на вкладке **Initiator** (Инициатор). Вообще говоря, чем короче цепочка запросов, тем быстрее можно запросить шрифт.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/0tau1GQnZfj5vPhzwnIQ.png", alt="Снимок экрана со вкладкой Initiator (Инициатор) в DevTools", width="800", height="189" %}

#### Решение проблемы

В нашей демонстрации используется API Google Fonts. Google Fonts позволяет загружать шрифты с помощью тегов `<link>` или оператора `@import`. Фрагмент кода тега `<link>` включает подсказку ресурса `preconnect`. Это должно привести к более быстрой доставке таблиц стилей, чем при использовании версии с оператором `@import`.

На очень высоком уровне можно считать [подсказки ресурсов](https://www.w3.org/TR/resource-hints/#resource-hints) способом сообщить браузеру, что ему потребуется настроить определенное соединение или загрузить определенный ресурс. В результате браузер сделает эти действия приоритетными. При использовании подсказок ресурсов имейте в виду, что если сделать определенное действие приоритетным, это отнимет часть ресурсов браузера, которые можно было бы потратить на другие действий. Таким образом, подсказки ресурсов следует использовать вдумчиво и не для всего подряд. Дополнительные сведения см. в статье «[Заблаговременное создание сетевых подключений для повышения воспринимаемой скорости работы страницы](/preconnect-and-dns-prefetch/)».

Удалите из таблицы стилей следующий оператор `@import`:

```css
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400&family=Roboto:wght@300&display=swap');
```

В элемент `<head>` документа добавьте следующие теги `<link>`:

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet">
```

Эти теги link сообщают браузеру, что нужно заблаговременно создать подключение к источникам, используемым Google Fonts, и загрузить таблицу стилей, содержащую объявления для шрифтов Montserrat и Roboto. Такие теги `<link>` следует размещать как можно раньше в элементе `<head>`.

{% Aside %}

Чтобы загрузить только подмножество шрифта из Google Fonts, добавьте параметр API [`?text=`](https://developers.google.com/fonts/docs/getting_started). Например, если использовать параметр `?text=ABC`, будут загружены только символы, необходимые для рендеринга текста «ABC». Это хороший способ уменьшить размер файла шрифта.

{% endAside %}

## Анимации

В основном, анимации влияют на метрики Web Vitals, если они приводят к сдвигу макета. Старайтесь не использовать анимации двух типов: [анимации, изменяющие макет](/animations-guide/#triggers), и эффекты, «похожие на анимацию», при которых выполняется перемещение элементов страницы. Обычно такие анимации можно заменить более производительными эквивалентами, используя ряд свойств CSS, например [`transform`](https://developer.mozilla.org/docs/Web/CSS/transform), [`opacity`](https://developer.mozilla.org/docs/Web/CSS/opacity) и [`filter`](https://developer.mozilla.org/docs/Web/CSS/filter). Дополнительные сведения см. в статье «[Как создавать высокопроизводительные CSS-анимации](/animations/)».

### Выявление проблемы

Анимации с низкой производительностью можно выявлять c помощью аудита Avoid non-composited animations в Lighthouse.

{% Img src="image/j2RDdG43oidUy6AL6LovThjeX9c2/mXgypW9x3qgvmWDLbIZx.png", alt="Аудит Avoid non-composited animations в Lighthouse", width="512", height="132" %}

{% Aside 'caution' %}

Аудит Avoid non-composited animations в Lighthouse выявляет только *CSS-анимации* с низкой производительностью; анимации на основе JavaScript (например, при использовании функции [`setInterval()`](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) для «анимации» элемента) снижают производительность, но они не будут помечены при выполнении этого аудита.

{% endAside %}

### Решение проблемы

Измените последовательность анимации `slideIn` и используйте функцию `transform: translateX()`, а не переход с использованием свойства `margin-left`.

Было:

```css
.header {
  animation: slideIn 1s 1 ease;
}

@keyframes slideIn {
  from {
    margin-left: -100%;
  }
  to {
    margin-left: 0;
  }
}
```

Стало:

```css
.header {
  animation: slideIn 1s 1 ease;
}

@keyframes slideIn {
  from {
    transform: translateX(-100%);
  }

  to {
    transform: translateX(0);
  }
}
```

## Критически важный код CSS

Таблицы стилей блокируют рендеринг. Это означает, что когда браузер встречает таблицу стилей, он перестает загружать другие ресурсы, пока не загрузит и не проанализирует ее. Это может приводить к задержкам при загрузке самых крупных отображаемых элементов содержимого. Чтобы повысить производительность, можно [удалить неиспользуемый код CSS](https://css-tricks.com/how-do-you-remove-unused-css-from-a-site/), [встроить критически важный код CSS](/extract-critical-css/) и [отложить выполнение кода CSS, который не является критически важным](/defer-non-critical-css/#optimize).

## Вывод

Несмотря на то что возможности для дальнейшей оптимизации страницы не исчерпаны (например, можно [сжимать изображения](/use-imagemin-to-compress-images/), чтобы быстрее доставлять их), выполненные изменения значительно улучшили метрики Web Vitals для этого сайта. Если бы это был настоящий сайт, на следующем этапе следовало бы [собрать данные о производительности от реальных пользователей](/vitals-measurement-getting-started/#measuring-web-vitals-using-rum-data), чтобы оценить, соответствует ли сайт [пороговым значениям метрик Web Vitals для большинства пользователей](/vitals-measurement-getting-started/#data-interpretation). Дополнительные сведения о Web Vitals см. в статье «[Изучение Web Vitals](/learn-core-web-vitals/)».
