Веб-шрифты и производительность — Примеры

Пример 1 — Два файла начертаний и текст, скрытый на время загрузки

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

@font-face {
  font-family: "Body";
  src: url("/fonts/body-regular.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}

@font-face {
  font-family: "Body";
  src: url("/fonts/body-bold.woff2") format("woff2");
  font-weight: 700;
  font-display: block;
}

Решение

@font-face {
  font-family: "Body";
  src: url("/fonts/body-variable.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0000-00FF;
}
<link rel="preload" href="/fonts/body-variable.woff2" as="font" type="font/woff2" crossorigin />

font-display: block скрывает текст, пока шрифт не готов; на медленном соединении это секунды пустой страницы. swap рисует запасной шрифт сразу и заменяет его, когда файл придёт, поэтому текст читаем всё время. Вариативный шрифт упаковывает весь диапазон начертаний в один файл — так два запроса превращаются в один. А сведение к символам, которые сайт действительно использует, часто уменьшает его ещё вдвое. Файл отдавайте со своего источника, а не со стороннего хостинга шрифтов. Предзагружайте только то начертание, которое отрисовывает первый экран: crossorigin обязателен даже для своего источника, иначе браузер скачает шрифт дважды.

Пример 2 — Подмена, которая сдвигает страницу

Шрифт загружается правильно, и текст заметно дёргается, когда заменяет запасной. Запись сдвига макета показывает смещение на пятую часть высоты страницы. Скажите, откуда берётся движение, и уменьшите его.

@font-face {
  font-family: "Body";
  src: url("/fonts/body.woff2") format("woff2");
  font-display: swap;
}

body { font-family: "Body", Arial, sans-serif; }

Решение

@font-face {
  font-family: "Body Fallback";
  src: local("Arial");
  size-adjust: 105%;
  ascent-override: 92%;
}

body { font-family: "Body", "Body Fallback", sans-serif; }

Сдвиг вызван не самой подменой, а расхождением метрик двух шрифтов. Arial немного уже и стоит на другой базовой линии, поэтому каждая строка переносится заново, и содержимое ниже смещается, когда его заменяет Body. Запасное начертание, объявленное локально с size-adjust и переопределением подъёма, масштабирует глифы и базовую линию подставного шрифта под загруженный. Так убирается большая часть движения, но мгновенная отрисовка, которую даёт swap, сохраняется. Выбирайте запасной шрифт по близким пропорциям сразу. Тестируйте с ограниченной сетью и проверяйте сдвиг в трассировке, а не на глаз на быстром локальном соединении.