Как правильно загружать посторонние шрифты? — спрашивают наши зрители Алексей и Марат. Спасибо за важный вопрос, ребята. Плохим подключением шрифтов можно очень сильно навредить загрузке сайта, вплоть до невозможности его прочесть. К счастью, есть надёжные варианты и даже новое свойство font-display. Давайте разберёмся!

Скажу сразу: лучший шрифт — тот, который вы не подключили. Прошло уже 20 лет с тех пор, как Microsoft подарила вебу корневой набор шрифтов, и они уже всем надоели: Arial, Courier, Georgia, Trebuchet, Verdana и другие. Но с тех пор появилось много других хороших встроенных семейств: Roboto на Android, San Francisco на macOS и iOS, Segoe UI на Windows. И при желании, можно насобирать приличных комбинаций для любого интерфейса.

Более того, набирает популярность мода использовать системный шрифт на каждой из платформ. Можно написать магическое заклинание font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto и так далее — и вы получите знакомый глазу шрифт. Так уже сделал Medium, WordPress, Booking, ВКонтакте и другие. Готовьтесь к крикам и угрозам от постоянных пользователей, но через пару недель они забудут, что было иначе.

font-family:
  -apple-system,
  BlinkMacSystemFont,
  Segoe UI, Roboto,
  Oxygen, Ubuntu,
  Cantarell, Fira
  Sans, Droid Sans,
  Helvetica Neue,
  sans-serif;

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

Для подключения шрифтов есть директива @font-face, где на сегодня нужно подключить две версии: WOFF и WOFF 2. Это такой специальный контейнер, который очень эффективно сжимает шрифт и поддерживается даже в IE9. WOFF 2 сжимает лучше всего, поэтому указывайте его первым. Никаких TTF, OTF, SVG, EOT — эти контейнеры слишком неэффективные и нужны в браузерах, которых уже нет в вашей статистике.

@font-face {
  font-family: Font;
  src: url('font.woff2')
         format('woff2'),
       url('font.woff')
         format('woff');
}

Там же можно указать локальные псевдонимы шрифта: в одном название, в другом его PostScript-версию — на случай если они уже установлены в системе. Например, вы можете не загружать Roboto на Android или Ubuntu на Ubuntu — они системные. Многие не знают, что в macOS уже давно встроен шрифт PT Sans, Serif и Mono. Браузер сначала попробует найти их локально и только потом, если не найдёт, пойдёт загружать. Такой способ использует Google Fonts, когда вы подключаете в голову документа стили с параметрами.

src:
  local('Roboto Light'),
  local('Roboto-Light')
src:
  local('PT Sans'),
  local('PTSans-Regular')

В отдельных директивах подключаются все нужные начертания: прямое, жирное, курсив, жирный курсив. Если в каждой из директив указывать одно и то же название, а комбинацией font-weight и font-style описать подключаемый шрифт, то использовать его будет проще. Если элемент унаследовал font-family от родителя, то сменить начертание можно будет с помощью font-weight и font-style. И не нужно будет для каждого задавать разные font-family.

Когда браузер видит директиву @font-face, он не бросается тут же всё загружать — в отличие от фоновых картинок. Он парсит весь остальной CSS и ждёт момента, когда текст нужно будет отрендерить этим шрифтом. И только тогда посылает запрос за файлами. Вы даже можете завернуть это в медиавыражение, мол, пока окно шире 320 пикселей — не нужно ничего загружать. Это очень полезная особенность, она нам ещё пригодится.

@media
  (max-width: 320px) {
    body {
      font-family:
        Font,
        sans-serif;
    }
  }

Если браузер сразу видит, что ему нужен шрифт — он начинает его загружать. И в этот момент происходит ужасное: большинство браузеров показывают сайт, но прячут текст, который ждёт шрифта, пока он не загрузится. Этот эффект называется FOIT или мелькание невидимого текста. К счастью Chrome, Firefox и Safari 10 перестают ждать после 3 секунд и показывают следующий шрифт по списку. Вот почему важно иметь подходящий запасной список. Chrome на медленных сетях вообще не ждёт, а Safari 9 и старые Android ждут как Хатико — до последнего.

Лучше всего в такой ситуации действуют IE и Edge, прикиньте? Они никогда не прячут текст и всегда показывают следующий системный шрифт, пока грузится внешний. Когда шрифт загрузился — текст перерисовывается. Это может приводить к неприятным скачкам, которые кидают страницу туда-сюда как плохие картинки без размеров. Этот эффект называется FOUT или мелькание текста без стилей. Но, знаете, лучше пусть текст прыгнет пока я его читаю, чем не прыгнет, пока я его не вижу — правда? Этот эффект считается наиболее удачным и его пытаются воспроизвести разными способами: от скриптов до новых CSS-свойств.

Лучший скрипт для имитации FOUT — это «Font Face Observer» Брэма Штайна — всего 3,5 килобайта. Он умеет загружать шрифты, следить за их появлением и делать что-то в результате. Можно использовать как шрифты из ресурсов сайта, так и сторонние из Google Fonts, Typekit и других. Вы прячете использование шрифта за класс в HTML, который выставляет скрипт при загрузке. Браузер видит это и перерисовывает текст. После удачной загрузки полезно ещё кидать флаг в sessionStorage и проверять его в самом начале — пока окно открыто, скрипт не нужен.

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

Если вас всё-таки прижали к стене и требуют избавиться от прыжков при загрузке — слишком уж непохож системный шрифт на фирменный — вариант есть. Можно повозиться и подогнать системный под нужный, подстроив размер, высоту строки и другие параметры. Моника Динкулеску даже сделала для этого специальный инструмент Font Style Matcher, который поможет сравнить варианты и подобрать очень похожий. Все ссылки в описании.

Вариантов и стратегий загрузки довольно много — есть даже специальный Font Loading API в браузерах, для полного контроля. Если вам нужно разобраться и найти идеальное решение — читайте статьи Брэма Штайна и Зака Лезермана, самых авторитетных авторов по загрузке шрифтов. Оценить успех ваших экспериментов поможет замедление или тротлинг сети во вкладке Network отладчика Chrome. Включите GPRS и узнайте много неутешительного о своём сайте.

Но это всё костыли! Почему бы всем браузерам просто не сделать как IE и Edge? — спросите вы. Потому, что можно ещё лучше. Новое свойство font-display уже год сидит за флагами в Chrome и Firefox и на днях появилось в стабильном Chrome 60. Оно позволяет контролировать как именно браузер рендерит шрифты при загрузке. Значение block прячет текст на три секунды и долго ждёт загрузки, swap делает похоже, но показывает системный шрифт сразу, fallback почти сразу показывает системный и недолго ждёт загрузку, optional — как fallback, но браузер уже сам решает стоит ли загружать шрифт.

Запомните главное: просто так подключить font-family и надеяться, что браузер сам всё разрулит, пока рано — поддержка font-display ещё слабая. Подберите хороший системный шрифт и подключите внешний через Font Face Observer — ваши пользователи скажут вам спасибо.