Front-end - оптимизация - шрифты - рендеринг

Привет.


Давай продолжим оптимизировать шрифты.


# Рендеринг шрифта в браузере

Рендеринг шрифтов в разных браузерах происходит по разному.


Хромиумы ничего не показывают, ждут 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.

Поддержка маленькая, но ничего не мешает начать применять его. Браузеры, которые не понимают данное свойство, просто проигнорируют его.

Front-end - оптимизация - шрифты - рендеринг Frontend, Optimization, Шрифт, Длиннопост

Новое свойство имеет несколько значений:

* 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 не обойтись.

### Как браузер понимает, когда нужно загрузить шрифт?

Во-первых у шрифта самый высокий приоритет загрузки

Front-end - оптимизация - шрифты - рендеринг Frontend, Optimization, Шрифт, Длиннопост

Если ты подключаешь шрифт с помощью 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. это серия постов про оптимизацию. Про шрифты ещё будет дополненение, но не хотелось бы уйти за лимит поэтому решил разбить на несколько частей.