---
title: Предотвращение сдвигов макета и мигания невидимого текста (FOIT) путем предварительной загрузки дополнительных шрифтов
subhead: 'В Chrome 83 появилась возможность полностью избавиться от искажений макета, используя элементы link rel="preload" и font-display: optional'
authors:
  - houssein
date: 2020-03-18
hero: image/admin/wv5DLtYiAhHm4lNemN1E.jpg
alt: Прописная буква A из типографского набора, лежащая на белом столе.
description: 'Благодаря оптимизации циклов рендеринга в Chrome 83 можно предотвратить смещение макета при предварительной загрузке дополнительных шрифтов. Использование элементов <link rel="preload"> и font-display: optional — самый эффективный способ обеспечить безупречный рендеринг пользовательских шрифтов.'
tags:
  - blog
  - performance
  - fonts
feedback:
  - api
---

{% Aside %} В Chrome 83 был усовершенствован процесс загрузки шрифтов, что позволило полностью избавиться от смещений макета и мигания невидимого текста (FOIT) при предварительной загрузке дополнительных шрифтов. {% endAside %}

Благодаря оптимизации циклов рендеринга в Chrome 83 можно предотвратить смещение макета при предварительной загрузке дополнительных шрифтов. Использование элементов &lt;link rel="preload"&gt; и font-display: optional — самый эффективный способ обеспечить безупречный рендеринг пользовательских шрифтов.

## Совместимость с браузерами {: #compatibility }

Актуальные сведения о поддержке в разных браузерах см. в MDN по указанным ниже ссылкам.

- [`<link rel="preload">`](https://developer.mozilla.org/docs/Web/HTML/Preloading_content#Browser_compatibility)
- [`font-display`](https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display#Browser_compatibility)

## Рендеринг шрифтов

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

- Замена резервного шрифта новым («мигание текста без стиля»)
- Отображение «невидимого» текста до тех пор, пока не будет выполнен рендеринг нового шрифта на странице («мигание невидимого текста»)

С помощью свойства CSS [`font-display`](https://font-display.glitch.me/) можно изменить поведение пользовательских шрифтов при их рендеринге, используя для этого поддерживаемые значения (`auto`, `block`, `swap`, `fallback` и `optional`). Выбор используемого значения зависит от того, как должны вести себя асинхронно загружаемые шрифты. Однако до сих пор использование каждого из этих значений может приводить к повторному созданию макета при выполнении двух указанных выше операций.

{% Aside %} Нестабильность макета на веб-странице можно измерить с помощью метрики [Cumulative Layout Shift](/cls/) (Совокупный сдвиг макета). {% endAside %}

## Дополнительные шрифты

Для свойства `font-display` используется временная шкала, состоящая из трех указанных ниже периодов. Она применяется для обработки шрифтов, которые требуется загружать, прежде чем выполнять их рендеринг.

- **Блокирование:** рендеринг «невидимого» текста и переключение на веб-шрифт сразу по окончании его загрузки.
- **Замена:** рендеринг текста с использованием резервного системного шрифта и переключение на веб-шрифт сразу по окончании его загрузки.
- **Ошибка:** рендеринг текста с использованием резервного системного шрифта.

Раньше для шрифтов, помеченных элементом `font-display: optional`, использовался период блокирования длительностью 100 мс и не использовался период замены. В этом случае перед переключением на резервный шрифт ненадолго отображается «невидимый» текст. Если не удается загрузить нужный шрифт в течение 100 мс, используется резервный шрифт, и замена шрифта не выполняется.

<figure>{% Img src="image/admin/WHLORYEu864QRRveFQUz.png", alt="Схема, на которой показано, что раньше происходило на странице, если не удавалось загрузить дополнительный шрифт", width="800", height="340" %} <figcaption>Действия, которые раньше выполнял элемент <code>font-display: optional</code> в Chrome в случае загрузки нужного шрифта <b>по истечении</b> периода блокировки длительностью 100 мс</figcaption></figure>

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

<figure>{% Img src="image/admin/mordYRjmCCDtlMcNXEOU.png", alt="Схема, на которой показано, что раньше происходило на странице при своевременной загрузке дополнительного шрифта", width="800", height="318" %} <figcaption>Действия, которые раньше выполнял элемент <code>font-display: optional</code> в Chrome в случае загрузки нужного шрифта <b>до истечения</b> периода блокировки длительностью 100 мс</figcaption></figure>

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

Благодаря [оптимизации](https://bugs.chromium.org/p/chromium/issues/detail?id=1040632) в Chrome 83 удалось полностью избавиться от первого цикла рендеринга для дополнительных шрифтов, предварительно загружаемых с использованием элемента [`<link rel="preload'>`](/codelab-preload-web-fonts/). В результате браузер блокирует операцию рендеринга до тех пор, пока не будет загружен пользовательский шрифт либо не пройдет определенный период времени. В настоящее время период ожидания равен 100 мс, но в ближайшем будущем он, возможно, будет изменен для оптимизации производительности.

<figure>{% Img src="image/admin/zLldiq9J3duBTaeRN88e.png", alt="Схема, на которой показано, что теперь происходит на странице, если не удается загрузить предварительно загруженный дополнительный шрифт", width="800", height="353" %} <figcaption>Действия, которые сейчас выполняет элемент <code>font-display: optional</code> в Chrome, если шрифты предварительно загружены, но загрузка нужного шрифта завершается <b>по истечении</b> периода блокировки длительностью 100 мс (отсутствует мигание невидимого текста)</figcaption></figure>

<figure>{% Img src="image/admin/OEHClGFMFspaWjb3xXLY.png", alt="Схема, на которой показано, что теперь происходит на странице, если удается вовремя загрузить предварительно загруженный дополнительный шрифт", width="800", height="346" %} <figcaption>Действия, которые сейчас выполняет элемент <code>font-display: optional</code> в Chrome, если шрифты предварительно загружены и удается загрузить нужный шрифт <b>до истечения</b> периода блокировки длительностью 100 мс (отсутствует мигание невидимого текста)</figcaption></figure>

Выполняя предварительную загрузку дополнительных шрифтов в Chrome, можно избавиться от искажений макета и мигания текста без стиля. Это соответствует требуемому поведению, описанному в документе [CSS Fonts Module Level 4](https://drafts.csswg.org/css-fonts-4/#valdef-font-face-font-display-optional): использование дополнительных шрифтов никогда не должно приводить к повторному созданию макета, а пользовательские агенты могут приостанавливать рендеринг на соответствующий период времени.

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

## Заключение

Разработчики Chrome хотели бы, чтобы вы рассказали о своем опыте использования функции предварительной загрузки дополнительных шрифтов с учетом новых оптимизаций. Создайте [запрос](https://bugs.chromium.org/p/chromium/issues/entry), если у вас возникли какие-либо проблемы или вы хотите предложить новые функции.
