Привет.
Давай продолжим оптимизировать шрифты.
# Рендеринг шрифта в браузере
Рендеринг шрифтов в разных браузерах происходит по разному.
Хромиумы ничего не показывают, ждут 3 секунды и если шрифт загрузился, то показывают текст (FOIT), иначе системный.
IE/EDGE - ничего не ждёт, сразу показывает системный шрифт, и после завершения загрузки шрифта перерендеривает шрифт (FOUT).
## FOIT
FOIT (Flash of Invisible Text) — букв. «мелькание невидимого текста», когда во время загрузки веб-шрифта текст не отображается вообще, а после рендерится загруженный шрифт;
## FOUT
FOUT (Flash of Unstyled Text) — букв. «мелькание неоформленного текста», когда во время загрузки веб-шрифта текст отображается шрифтом по умолчанию (напр. системным); (лучше FOIT)
## FOFT
FOFT (Flash of Faux Text) — букв. «мелькание синтезированного текста», когда в промежутке между загрузкой основного веб-шрифта и его вариаций (жирный, курсив и т.д.) вместо этих вариаций браузер отображает особым образом измененный основной шрифт (так называемый «ложный жирный» и «ложный курсив». (чуть лучше FOUT)
## Лучшего варианта нет.
Каждый сам для себя решит как лучше, но можно точно сказать, что это не FOIT.
FOIT заставляет пользователя ждать и ничего не делать некоторое время.
FOUT даёт как можно быстрое взаимодействие с сайтом, но спустя время, когда шрифт загрузится, происходит перерисовка всего шрифта, которое даёт "скачок сайта".
FOFT это тоже самое, что и FOUT, но "скачков сайта" происходит несколько. Т.к. вначале загружается основное начертание шрифта, а остальные (жирное и наклонное) спустя время.
## Font-display
Самым современным вариант будет использовать новое css-свойство font-display.
Поддержка маленькая, но ничего не мешает начать применять его. Браузеры, которые не понимают данное свойство, просто проигнорируют его.
Новое свойство имеет несколько значений:
* auto - Использует поведение браузера по умолчанию. Обычно это поведение ‘block’.
* block - Устанавливает короткий период блокировки (3 секунды) и бесконечный период замены.
* swap - Устанавливает период блокировки в 0 секунд и бесконечный период замены.
* fallback - Устанавливает очень короткий период блокировки (100 мс или меньше) и короткий период замены (3 секунды).
* optional - Устанавливает очень короткий период блокировки (100 мс или меньше) и период замены в 0 секунды.
В этом видео очень подробно показано как это работает в живую.
### Периоды
* Период блокировки шрифта
Если шрифт не загружен, любой элемент, который пытается его использовать, должен быть отрендерен с невидимым запасным шрифтом. Если за это время шрифт успешно загружается, то он используется, как обычно.
* Период подмены шрифта
Если шрифт не загружен, любой элемент, который пытается его использовать, должен быть отрендерен запасным шрифтом. Если за это время шрифт успешно загружается, то он используется, как обычно.
* Период отказа шрифта
Если шрифт не загружен, пользовательский агент воспринимает это как неудачную загрузку и использует запасной шрифт.
### Применение
```
@font-face {
font-display: swap;
font-family: "opensans";
src: url("/fonts/OpenSans/Regular/OpenSans-Regular.woff2") format("woff2"),
url("/fonts/OpenSans/Regular/OpenSans-Regular.woff") format("woff");
font-weight: 400;
}
```
Самым часто применимым является значение - swap. По желанию конечно же можно сменить значение на выгодное вашему проекту.
Очень интересным является значение - optional. В этом случае, если шрифт не успел загрузится за 100ms, то рендеринг шрифта отменяется. Пользователь видит какой-нибудь системный шрифт, то есть может взаимодействовать с сайтом (да не красиво, ничего страшного) Шрифт при этом грузится в фоне. Позже при обновление страницы, шрифт оказывается в кеше и в этом случае происходит рендеринг.
## Font face observer
Если font-display не поддерживается, то без javascript не обойтись.
### Как браузер понимает, когда нужно загрузить шрифт?
Во-первых у шрифта самый высокий приоритет загрузки
Если ты подключаешь шрифт с помощью font-face и в стилях есть обращение к шрифту, то загрузка начнётся как можно быстрее. Всё зависит от того, где ты подключаешь стили, это может быть после блокирующего скрипта, что откладывает загрузки и стилей и шрифта.
В идеальном мире это проиходит вот так
1) DOMContentLoaded
2) Загрузка стилей
3) Если есть обращение к семейству шрифта, то загрузка шрифта
Что значит "Если есть обращение к семейству шрифта"?
Допустим, ты объявляешь шрифт
```
@font-face {
font-family: "OpenSans";
src: url('/path/fonts/OpenSans.woff2') format("woff2"),
url('/path/fonts/OpenSans.woff') format("woff")
}
```
а дальше в своих css-файлах нигде к нему не обращаешься, то загрузка шрифта не произойдёт. В этом просто напросто нет смысла и браузер следит за таким поведением.
Вернёмся к javasctipt.
В head секцую нащей страницы добавляем fontfaceobserver и подключим нужные шрифты с помощью плагина.
```
<head>
<script src="path/to/fontfaceobserver.js"></script>
<script>
var openSans = new FontFaceObserver('opensans', {weight: 400});
Promise.all(openSans.load()).then(function() {
document.documentElement.className += 'font-loaded';
});
</script>
</head>
```
Подлючаем одно или несколько начертаний шрифта. И как только они загрузятся добавляем класс font-loaded к тегу html.
В стилях делаем следующий трюк:
```
// список системных шрифтов пополярных операционных систем
html {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
"Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}
html.font-loaded {
font-family: "opensans", sans-serif;
}
```
Вначале показываем системные шрифты! Они кстати в современном мире достаточно красивые и удовлетворяют потребности дизайнера. После того как Javascript добавит класс font-loaded, подключаем "opensans".
P.S. это серия постов про оптимизацию. Про шрифты ещё будет дополненение, но не хотелось бы уйти за лимит поэтому решил разбить на несколько частей.