[Из песочницы] Шрифты в вебе, обзор от 2016 года
Предисловие
Статья — не про всё возможное, связанное с типографикой и текстами, вроде letter-spacing и max-height. Это скорее некоторый список занятных возможностей, которые могут быть углублённо изучены при наличии достаточного любопытства и времени. Надеюсь, для большей части найдётся то, что они не знали или слышали краем уха.
Вступление
В 2016 году нестандартными шрифтами никого не удивишь. 93% браузеров поддерживают их, и около 62% сайтов их используют. Кто-то просто пишет @font-face или вставляет с Google Fonts, кто-то вставляет мегабайт шрифтов в base64 прямо в css. Возможностей много.
Загрузка
Статья была бы неполной без таблички разного поведения браузеров во время загрузки шрифтов, но я не могу себе позволить её вставить — она так часто встречается, что уже, вероятно, вызывает нервный тик.
Общие понятия:
FOIT — flash of invisible text. Сначала отрисовывается страница без текста, затем — сразу с нужным шрифтом.
FOUT — flash of unstyled text. Сначала используется один шрифт, затем — загруженный.
FOFT — некоторые выделяют такой подтип проблем, но встречается реже.
Очень хорошо описаны различные стратегии загрузки шрифтов в недавней статье от Zach Leatherman (русская версия), каждая со своими плюсами и минусами. Я же попробую дать упрощённый обзор различных вариантов: если понадобится изучить, набор ссылок будет под рукой.
@font-face без дополнительных ухищренийВстречается часто, можно оставить всё как есть на откуп браузеру. Также плюс в том, что пользователи, скорее всего, уже привыкли к такому поведению и не замечают проблем. Минусы: разное поведение в разных браузерах, спорное поведение в некоторых случаях. В сафари и некоторых других браузерах в случае проблем загрузки шрифта может вообще ничего не отображаться длительное время…
Плюсы:
- Не требует дополнительных усилий
- Скорее всего, пользователи привыкли к такому поведению и редко заостряют на этом внимание
Минусы:
- Разное поведение в разных браузерах
- Спорное поведение в некоторых случаях
Библиотека для определения загрузки шрифта
Общая идея: используем стандартный шрифт до загрузки, после загрузки переключаем класс на body и на всей странице включаются новые шрифты. Это похоже на стандартное поведение Internet Explorer и Edge.
Плюсы:
- Контроль за использованием шрифтов
- Небольшой размер библиотек
- Просто использовать
Минусы:
- Переключение шрифта заметно пользователю
- Может приводить к перемещению элементов на странице из-за смены размера текста
- Требуются дополнительные ухищрения для отсутствия перерисовки шрифта при перезаходе: флаги в куках, sessionStorage
Ссылки:
- Web Font Loading Patterns (русская версия)
- FontFaceObserver
- FontFaceOnload
Кодирование шрифта в base64
Самый разнообразный способ. Можно инлайнить шрифт прямо в основной файл стилей, грузить их асинхронно или вовсе складывать в localStorage. Для кого-то окажется неожиданным то, что после gzip размер отличается от бинарного файла совсем немного.
Плюсы:
- В общем случае не нужны дополнительные библиотеки для определения загрузки шрифтов
- При использовании вместе с основной частью css делает ситуации с foit и fout гораздо реже
- При сохранении в localStorage всё кеширование шрифтов в наших руках
Минусы:
- Теряется поддержка нескольких типов шрифтов. Либо нужно их дублировать (и тем самым увеличивать общий размер), либо выбрать наиболее распространённый (например, woff и потерять экономию от woff2)
- Окончание загрузки css — не гарант того, что шрифт может быть сразу отображён! Как и вставка этого css напрямую в страницу. Браузерам требуется время на парсинг шрифтов перед их использованием. Всё это выливается в три стадии отрисовки: дефолтный шрифт, foit, нужный шрифт
- При вставке просто в css будет задерживать первую отрисовку всей страницы
Ссылки:
- Описание сохранения шрифтов в localStorage
- Скрипт загрузки шрифтов с сайта smashingmagazine.com
- Web Font anti-pattern: data-uris (русская версия)
font-display
Новое css-свойство, которое позволяет контролировать отображение шрифтов во время загрузки. Плюсы-минусы очевидны: простота в использовании и слабая поддержка (скорее, никакая).
Это не совсем способ загрузки, а некоторая оптимизация. С помощью preload можно сократить время до окончания загрузки веб-шрифтов, попутно уменьшить вероятность foit. Браузеры на основе Blink начинают загружать шрифты только после того, как найдут текст на странице с соответствующим шрифтом, а это сильно откладывает окончательный показ страницы: нужно загрузить css, распарсить её, применить к дом-дереву и найти нужный элемент. preload указывает браузеру, что указанный ресурс стоит грузить прямо сейчас. Требуются атрибуты as, type и crossorigin.
Ссылки:
- Использование preload для шрифтов (русская версия)
Всё остальное
Есть ещё несколько вариаций всего перечисленного, а также вариант через JS (об этом ниже). Например, можно загрузить только одно начертание шрифта, а все остальные использовать при повторных заходах. Или сильно урезать набор используемых символов шрифта (до 5–10 кб) и положить всё это в base64. А может, на первом заходе вообще не использовать на первом заходе нестандартные шрифты, а только загружать их? Также можно не использовать шрифты, если текста почти нет: для логотипов вполне подойдёт SVG. Что выбрать? Каждый решает сам для себя, на основе дизайна, шрифта (-ов) и аудитории.
FontFace
Новое js-api позволяет загружать и использовать шрифты, не используя объявление @font-face вообще. Несколько примеров, чтобы было понятно, о чём речь:
var f = new FontFace("newfont", "url(newfont.woff)", {});
f.load().then(function (loadedFace) {
document.fonts.add(loadedFace);
document.body.style.fontFamily = "newfont, serif";
});
fetch('newfont.woff2').then(
res => res.arrayBuffer()
).then(
buf => new FontFace("newfont", buf)
).then(ff => {
document.fonts.add(ff)
});
Троеточие — не часть кода.
new FontFace('t', 'url( "data:application/font-woff2;base64, <...>")').load();
Проблема в том, что понять, какой формат поддерживается, напрямую нельзя. Поддержка браузерами тоже не полная, но к ней добавится Safari 10. FontFace может быть полезен при отрисовке текста через canvas, так как не придётся создавать невидимые элементы с текстом.
Ссылки:
- CSS Font Loading Module Level 3
- Woff2 feature test
- Пример использования
CSS-свойства
font-weight и font-style
font-weight — достаточно известное свойство. Часто можно увидеть bold, реже — что-то со значением в числах. Стоит отметить то, что веб всё чаще выбирается из bold/italic/bold-italic, сейчас можно увидеть всевозможные thin, light, medium (таких ключевых слов нет, но для них как раз используются числовые значения). Другой интересный вопрос — что делают браузеры, если нужного начертания нет в наличии? В случае жирного/курсивного начертания они пытаются сгенерировать глифы на основе обычной вариации шрифта.
Ссылки:
- Три способа использования разных начертаний
- Статья на MDN с примерным описанием алгоритма фолбека
- Правильное подключение нескольких начертаний одного шрифта
- Табличка с использованием bolder и lighter
- Статья на MDN с описанием CSS-свойства font-synthesis
unicode-range
Данное свойство позволяет указать список символов, которые должны быть отображены шрифтом. Это может быть полезно в качестве оптимизации — если на странице не будет символов из этого списка, шрифт не будет загружен вовсе. Также unicode-range можно использовать для стилизации отдельных символов, например, кавычек или для отображения символа рубля. Проблема может быть в поддержке этого свойства браузерами, и хотя она постепенно уходит, всё равно нужно думать: «а что, если бы unicode-range не было».
Ссылки:
- Статья на MDN с описанием unicode-range
- Старая статья про стилизацию амперсандов
- Атака на сайт с помощью инъекции css с unicode-range
font-variant и font-feature-settings
font-variant — несколько обновлённый вариант font-feature-settings. Эти свойства позволяют задействиовать дополнительные возможности, включённые в шрифт. Например, кернинг, диагональные дроби, лигатуры и различные варианты иероглифов.
Ссылки:
- Описание различных значений font-feature-settings
text-rendering
Свойство задумывалось как обобщённый регулятор скорости отрисовки шрифта, влияя одновременно на кернинг и лигатуры. Несмотря на свою мощность, свойство не получило значительного распространения и заслужило славу бажного и тормозного. В настоящее время имеет смысл воспользоваться font-variant и font-kerning, они дают больше контроля (если не так важна поддержка браузерами, а иначе — font-feature-settings). На самом деле, text-rendering является свойством SVG и не описано ни в одной спецификации CSS.
Ссылки:
- Описание text-rendering с примерами
- Описание использования и проблем с text-rendering (русская версия)
font-kerning
font-kerning контролирует работу кернинга (отступы между отдельными сочетаниями букв). Для включения требуется информация о кернинге внутри самого шрифта. Является более современной заменой части функционала font-feature-settings.
Ссылки:
- Работа с кернингом в браузере, включая таблицы поддержки text-rendering и font-feature-settings (правда. несколько устаревшие)
- Статья на MDN вместе с интерактивной демкой свойства
font-stretch
Редкоиспользуемое свойство с тяжёлой судьбой. Введённое в CSS 2 и поддержанное в Firefox 9 с Internet Explorer 9, оно было удално из CSS 2.1 и забыто до CSS 3, а не так давно было добавлено в Chrome 48. Оно позволяет использовать альтренативные начертания шрифта, более узкие или широкие.
Использование встроенных шрифтов
В OS X и iOS очень интересная ситуация с системными шрифтами. Недавно там были представлен San Francisco в качестве основного шрифта интерфейса системы. И если Helvitica Neue можно было указать прямо в font-family (хоть порой в сложном варианте), то с San Francisco такой способ был намеренно затруднён. По новой логике, чтобы разработчики не затачивались на какой-то конкретный шрифт, в таких случаях нужно использовать ключевые слова »-apple-system-*», которые поддерживаются с iOS 7. Как аналог, в десктопном хроме недавно добавили значение BlinkMacSystemFont.
В Android есть шрифт Roboto, который недоступен по своему имени. Однако можно использовать простые sans-serif, sans-serif-light, sans-serif-medium и другие.
Из-за лицензии, в общем случае нельзя просто взять и положить на свой сервер чьи-то системные шрифты. Допускается только указание их в css, так как тогда заботы о лицензии установленных в систему шрифтов ложатся на плечи пользователя.
Ссылки:
- Описание шрифтов -apple-system
- Использование системных шрифтов в вебе (русская версия)
- Список названий начертаний Roboto в андроиде, вместе с минимальной версией (ответ про приложения, но в вебе тоже работает)
- Список названий начертаний Helvetica Neue
- Список предустановленных шрифтов в Windows
- Список предустановленных шрифтов в OS X
- Список предустановленных шрифтов в iOS, watchOS, tvOS
Оптимизация
Самое простое — использовать оптимальный формат. Появившийся не так давно woff2 некоторые оценивают как лучший вариант для шрифтов, из-за примерно 30% уменьшения размера файла по сравнению с woff. Судя по caniuse — woff2 скоро будет поддерживаться в Edge и должен быть в новом Safari 10.
Другой способ — убрать неиспользуемую информацию из самого шрифта, например, лигатуры или наборы символов из неиспользуемых языков. Также есть возможность упростить сами векторные кривые символов — иногда в них слишком много точек и их можно задать проще.
Ссылки:
- FontSquirrel. Сайт, позволяющий конвертировать шрифты, удалять неиспользуемые начертания символов, кодировать в base64 и многое другое
- FontForge, приложение-редактор шрифтов. Низкоуровневый инструмент — можно удалять отдельные глифы, упрощать кривые, удалять кернинг, вплоть до сдвига отдельных точек
- Советы по оптимизации от Google
- fontTools. Библиотека на питоне для манипуляции шрифтами
- Консольная утилита для конвертации ttf > woff2
Определение текущего шрифта элемента
Иногда стоит задача определения текущего шрифта элемента. В случае разработки могут помочь Chromium Developer Tools и недавно вернувшаяся панелька Fonts из Firefox. В ином случае остаётся только считать размер элемента и сравнивать его после смены значения font-family. Примерно этим занимаются FontFaceOnload и FontFaceObserver, если в браузере недоступен js-интерфейс FontFace. Почему браузеры не предоставляют для этого внятного апи? Дело в том, что отдельные символы внутри одного элемента могут быть отрисованы разными шрифтами, которые перечислен в font-family. На это может влиять упомянутый выше unicode-range и сам набор глифов шрифта.
Где взять нестандартные шрифты?
- https://fonts.google.com/
- https://www.fontshop.com/
- https://www.fontsquirrel.com/
- Напишите в комментариях свой вариант
Прочее
- Как растровый шрифт медиум сломал
- Стоит ли вообще использовать нестандартные шрифты?
Комментарии (2)
15 сентября 2016 в 11:01
0↑
↓
Ни на белке, ни на гугле не нашел аналога всеми любимой Проксимы. Lato вообще кириллический есть только на белке. Gilroy вроде похож, но не совсем то, и бесплатен только в двух начертаниях. Есть какие-то другие варианты?15 сентября 2016 в 11:21
0↑
↓
На мой взгляд, самый лучший шрифт выглядит так (украдено из twbs@4):font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;