typographyMay 3, 202616 min read

Вариативные шрифты в продакшене: как выкатить их и не угробить производительность

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

By Boone
XLinkedIn
variable fonts in production

Вариативные шрифты в продакшене: как выкатить их и не угробить производительность

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

Вариативный шрифт — это один файл с бесконечным числом начертаний

Вариативный шрифт упаковывает все начертания по насыщенности, наклону и ширине в один файл с осями, между значениями которых можно интерполировать. В этом весь питч и весь компромисс. Один сетевой запрос заменяет от четырёх до семи запросов статических шрифтов. Файл больше любого отдельного статического начертания, но меньше полного набора статических начертаний вместе взятых. Такова сделка.

Формат — OpenType со встроенными данными вариативности. Браузер интерполирует между крайними значениями осей прямо при рендеринге, а значит, font-weight: 350 или font-weight: 723 вы получаете бесплатно, а не только целые числа, которые решила выпустить словолитня. Именно это делает возможным паттерн анимации насыщенности при наведении, и именно из-за этого небрежная реализация грузит файл на 600 килобайт ради сайта, где используются всего два начертания.

Четыре оси, которые стоит отдавать

Насыщенность, наклон, оптический размер, ширина. Большинству продакшен-сайтов нужны две или три из них, а отдавать больше осей, чем вы используете, значит впустую тратить байты.

Спецификация OpenType определяет пять зарегистрированных осей: насыщенность (wght), ширина (wdth), наклон (slnt), курсив (ital) и оптический размер (opsz). Помимо них словолитни могут определять кастомные оси для чего угодно, от градации до экспрессивности. Кастомные оси радуют в типографском образце. В продакшене они почти никогда не стоят своего размера файла. Держитесь четырёх зарегистрированных осей, если только дизайн прямо не требует чего-то другого.

ОсьCSS-свойствоТипичный диапазонКогда использовать
Насыщенность (wght)font-weight100–900Почти всегда
Ширина (wdth)font-stretch75%–125%Редакционные и адаптивные заголовки
Наклон (slnt)font-style: oblique Xdegот -15deg до 0degЗамена настоящего курсива или анимация
Оптический размер (opsz)font-optical-sizing6–144Акцидентный и текстовый набор из одного файла
Воксельная концепция, показывающая четыре оси вариативного шрифта (насыщенность, ширину, наклон и оптический размер) как отдельные измерения одного файла гарнитуры
Воксельная концепция, показывающая четыре оси вариативного шрифта (насыщенность, ширину, наклон и оптический размер) как отдельные измерения одного файла гарнитуры

Насыщенность — рабочая лошадка

Ось насыщенности заменяет от четырёх до семи файлов статических начертаний, которые отдаёт большинство сайтов, и она одна окупает вариативные шрифты. Сайт, отдающий Regular, Medium, SemiBold, Bold и ExtraBold статическими файлами, делает пять запросов шрифтов. Вариативный шрифт с осью насыщенности делает один и бесплатно отдаёт все промежуточные значения.

В CSS это font-weight: 300 вплоть до font-weight: 900 на любом элементе. Промежуточные значения вроде font-weight: 450 валидны и отрисовываются корректно. Прежде чем считать, что вариативный шрифт покрывает весь диапазон от 100 до 900, проверьте документацию словолитни по диапазону оси. Некоторые отдают более узкий диапазон и молча обрезают значения, из-за чего вместо плавных переходов получаются едва заметные, но уродливые ступеньки.

Наклон открывает настоящие курсивы

Настоящая ось наклона позволяет переходить от прямого начертания к наклонному при любом значении, чего большинство пар статических шрифтов без второго файла сделать не могут. Различие между slnt (наклон) и ital (курсив) важно: наклон — это непрерывный диапазон от прямого начертания к oblique, а курсив — бинарный переключатель на отдельный, оптически скорректированный курсивный рисунок.

Для основного текста почти всегда правильный выбор — ось курсива с нормальным оптическим курсивом. Для заголовков, которые вы планируете анимировать, нужна ось наклона. В CSS это font-style: oblique -10deg, где значение в градусах соответствует диапазону оси. Проверьте наклон на реальном размере заголовка, прежде чем фиксировать значение. Экстремальные углы наклона на малых размерах выглядят хуже, чем обещает типографский образец словолитни.

Оптический размер сохраняет жизнь акцидентному набору

Оптический размер подстраивает контраст, x-высоту и детали под отображаемый размер, то есть встраивает в один шрифт разницу между акцидентной и текстовой гарнитурой. Гарнитура, рассчитанная на основной текст в 12px, имеет упрощённые детали, открытые внутрибуквенные просветы и щедрые интервалы. Акцидентное начертание в 80px имеет более резкий контраст, более плотные интервалы и более тонкую проработку деталей. Оптический размер даёт вам оба варианта из одного файла.

CSS-свойство — font-optical-sizing: auto, оно позволяет браузеру применять правильные оптические настройки на основе заданного font-size. Можно также задать вручную через font-variation-settings: 'opsz' 72 для заголовка в 72px. Шрифты, которые поддерживают эту ось как следует (канонический пример: Inter Display против Inter Text), проектировались с оптическим размером как полноценной функцией. Шрифты, в которые ось opsz добавили как запоздалую мысль, редко дают осмысленную визуальную разницу. Знайте, что именно вы покупаете.

Ширина — редакционная ось

Ось ширины позволяет сжимать заголовки и расширять цитаты-выноски без смены шрифтов, и именно этот ход заставляет редакционные макеты петь. CSS-свойство — font-stretch, оно принимает значения в процентах: font-stretch: 75% для узкого начертания, font-stretch: 125% для широкого.

Эта ось отрабатывает свой размер файла на сайтах с адаптивными редакционными макетами. Заголовку в 120px на десктопе может понадобиться сжатие, чтобы поместиться в колонку на мобильном экране шириной 375px, и ось ширины решает это одним @media-запросом вместо загрузки второго шрифта. Roboto Flex отдаёт один из самых широких диапазонов оси ширины среди готовых к продакшену вариативных шрифтов, и его стоит изучить, если вы планируете всерьёз использовать эту ось. Для маркетинговых сайтов с заголовками фиксированной ширины пропускайте её целиком.

Вариативный или статический: дерево решений

Вариативные шрифты выигрывают, когда вы используете три и более начертаний, анимируете шрифт или нуждаетесь в оптическом размере. В остальных случаях оставайтесь на статике. Точка безубыточности обычно лежит на двух-трёх начертаниях, а арифметика меняется в зависимости от требований к языковому покрытию.

СценарийЛучший выборПричина
1–2 начертания, без анимацииСтатическийМеньше байтов в сумме
3+ начертанияВариативныйОдин файл лучше трёх
Анимация насыщенности или наклонаВариативныйВозможна только с вариативным
Нужен оптический размерВариативныйЭкономит загрузку второго шрифта
Только узкая латиница, одно начертаниеСтатическийВариативный не даёт выгоды
Много локалей, много языковВариативный с сабсеттингомОдин базовый файл, расширения по локалям

Сайту с Regular и Bold, скорее всего, лучше два статических файла общим весом 40–60 килобайт, чем один вариативный шрифт на 120–200 килобайт. Арифметика решительно склоняется в пользу вариативного, как только вы переходите порог в три начертания или добавляете в требования анимацию.

Сабсеттинг режет файл вдвое

Сабсеттинг выбрасывает глифы, которые вы не используете, и на маркетинговом сайте это значит, что вариативный шрифт на 600 килобайт превращается в 200 килобайт без видимых изменений. Полный вариативный шрифт содержит каждый глиф, который нарисовала словолитня: латиницу, расширенную латиницу, кириллицу, греческий, математические операторы, символы валют и лигатуры, которые вам никогда не понадобятся. Вариативный шрифт после сабсеттинга содержит только то, что нужно вашему контенту.

Инструмент для этого — pyftsubset из библиотеки fonttools. Базовая команда для латинского сабсета:

bash
pyftsubset font.woff2 \ --output-file=font-subset.woff2 \ --flavor=woff2 \ --unicodes=U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD \ --layout-features="kern,liga,calt,rlig"

Оставляйте layout-фичи kern, liga, calt и rlig. Всё остальное вычищайте, если только дизайн явно не использует это. Прогоните результат через WOFF2-компрессор, если инструмент не сжал файл автоматически.

Воксельная концепция, иллюстрирующая обрезку файла вариативного шрифта сабсеттингом: неиспользуемые диапазоны глифов удаляются, и шрифт в 600KB сжимается до 200KB
Воксельная концепция, иллюстрирующая обрезку файла вариативного шрифта сабсеттингом: неиспользуемые диапазоны глифов удаляются, и шрифт в 600KB сжимается до 200KB

Latin, Latin-extended и языковые диапазоны

Правильная стратегия сабсеттинга — один латинский файл плюс по одному файлу языкового расширения на каждую локаль, загружаемому только при необходимости. Большинство маркетинговых и продуктовых сайтов отдают преимущественно латинский контент. Отдавайте латинский сабсет по умолчанию, а расширенные наборы символов подгружайте через дескриптор unicode-range в @font-face, который говорит браузеру скачивать файл только тогда, когда на странице встречаются подходящие символы.

css
@font-face { font-family: 'YourFont'; src: url('/fonts/yourfont-latin.woff2') format('woff2'); font-weight: 100 900; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { font-family: 'YourFont'; src: url('/fonts/yourfont-latin-ext.woff2') format('woff2'); font-weight: 100 900; font-display: swap; unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; }

Браузер скачивает только те файлы, которые соответствуют символам на текущей странице. Французская страница загрузит файл Latin Extended. Английская нет. Так Google Fonts работает в масштабе, и это правильный паттерн, который стоит копировать для собственных вариативных шрифтов.

Загрузка без дёрганий

Вариативный шрифт, который загружается после первой отрисовки, сдвинет макет, а рецепт загрузки — это preload плюс font-display swap плюс фолбэк с подогнанными метриками. Это не опционально. Вариативный шрифт больше одного статического начертания, а значит, дольше едет, а значит, окно для сдвига макета шире.

Ссылка preload идёт в <head>, перед любыми таблицами стилей:

html
<link rel="preload" href="/fonts/yourfont-latin.woff2" as="font" type="font/woff2" crossorigin >

Объявление font-display: swap в вашем @font-face говорит браузеру сразу рендерить текст фолбэком и подменить его вариативным шрифтом, когда тот приедет. Вариативный шрифт — это один файл с бесконечным числом начертаний, и неправильная стратегия загрузки загрузит его дважды впустую, если смешать объявления с preload и без него в разных таблицах стилей. Один preload на один файл сабсета. Вот и всё правило.


Хотите вариативные шрифты, которые весят вдвое меньше и никогда не дёргают страницу? Наймите Brainy, и мы выкатим вам продакшен-стек типографики с правильными осями, правильными сабсетами и рецептом загрузки, который держит Lighthouse зелёным.


Воксельная концепция последовательности загрузки вариативного шрифта: preload в head, font-display swap в CSS и фолбэк с подогнанными метриками, предотвращающий сдвиг макета
Воксельная концепция последовательности загрузки вариативного шрифта: preload в head, font-display swap в CSS и фолбэк с подогнанными метриками, предотвращающий сдвиг макета

Фолбэки с подогнанными метриками

Системный фолбэк с подогнанными метриками использует size-adjust, ascent-override и descent-override, чтобы фолбэк рендерился в том же ритме, что и вариативный шрифт. Без этого font-display: swap меняет невидимый текст на сдвиг макета в момент прихода вариативного шрифта. С подгонкой метрик подмена визуально незаметна.

css
@font-face { font-family: 'YourFont Fallback'; src: local('Arial'); ascent-override: 90%; descent-override: 22%; line-gap-override: 0%; size-adjust: 107%; }

Точные значения зависят от вашего вариативного шрифта. Инструменты вроде Fontaine и next/font генерируют эти значения автоматически. Если вы строите на Next.js, next/font берёт на себя всю цепочку фолбэков. Если нет, Fontaine — самый быстрый путь к корректным значениям override без ручных расчётов.

Четыре паттерна анимации, которые открывают вариативные шрифты

Hover-weight, scroll-weight, hover-slant и reveal-width. Эти четыре анимации возможны только с вариативными шрифтами, и они отрабатывают размер файла, если применять их скупо. Запихните все четыре на одну страницу, и она будет выглядеть как техно-демо, а не как дизайн.

Hover-weight переводит font-weight с 400 на 700 при наведении. Интерполяция плавная, потому что данные оси лежат в самом шрифте. transition: font-weight 0.15s ease на элементе — это весь CSS. Работает на навигационных ссылках, тексте призывов к действию и интерактивных подписях.

Scroll-weight управляет font-weight по позиции прокрутки с помощью JavaScript-слушателя scroll, который отображает scrollY на значение в диапазоне оси. Держите диапазон узким: от 300 до 700 выглядит намеренно, от 100 до 900 выглядит как баг. Место ему в hero-секциях, где шрифт тяжелеет по мере того, как пользователь прокручивает к контенту.

Hover-slant переводит font-style: oblique 0deg в font-style: oblique -10deg при наведении. Это более тонкая альтернатива hover-weight, и на навигационных ссылках и встроенных интерактивных элементах она выглядит изысканнее. Комбинируйте её с hover-weight, только если гарнитура проектировалась для одновременной поддержки обоих эффектов.

Reveal-width анимирует font-stretch как часть входной анимации. Текст появляется с font-stretch: 75% и расширяется до font-stretch: 100% за 400мс. В сочетании с плавным появлением это один из самых чистых типографских паттернов раскрытия. Пропускайте его на основном тексте. Ему место только на акцидентном наборе и hero-заголовках.

Семь сайтов, отдающих вариативные шрифты в масштабе

GitHub, Stripe Press, Vercel, Linear, The New York Times, Apple Music и Figma отдают вариативные шрифты в продакшене, и общие для них паттерны стоит копировать.

GitHub отдаёт Mona Sans и Hubot Sans, оба кастомные вариативные шрифты, сделанные под бренд GitHub. В большинстве контекстов UI только ось насыщенности. Никакой анимации, кроме редких маркетинговых секций. Размеры файлов скромные, потому что они агрессивно делают сабсеттинг по языковым группам.

Stripe Press использует кастомный акцидентный вариативный шрифт для редакционных заголовков. Они сильно давят на ось насыщенности: акцидентные заголовки тяжёлые, подписи лёгкие, и всё из одного файла. Оптический размер заметен на крупных размерах заголовков. Это самое редакционно амбициозное использование вариативного шрифта в этом списке.

Vercel отдаёт Geist, собственный вариативный шрифт, в вариантах Geist Sans и Geist Mono. Ось насыщенности покрывает весь диапазон. Шрифт с открытым исходным кодом, латинский сабсеттинг чистый, и грузится он достаточно быстро, чтобы служить эталоном того, как выглядит хорошо выкаченный вариативный шрифт в продакшен-приложении на Next.js.

Linear отдаёт Inter как вариативный шрифт. Ось насыщенности охватывает насыщенности для UI, оставаясь в более узком оптическом диапазоне, подходящем для плотного интерфейса. Это самое консервативное использование в списке и одновременно одно из самых верных для насыщенного данными продуктового интерфейса, где анимация была бы шумом.

The New York Times использует кастомную вариативную антикву для акцидентного набора. Оси насыщенности и оптического размера обе активны, а переходы между акциденцией и текстом используют ось оптического размера, чтобы менять характер отрисовки. Это максимум изощрённости для продакшен-использования вариативных шрифтов в редакционном масштабе.

Apple Music отдаёт San Francisco в вариативной форме с активными осями насыщенности и оптического размера. Переходы осей между крупным и мелким кеглем достаточно плавные, чтобы большинство пользователей не замечало, что шрифт вариативный, и это правильная цель. Шрифт должен растворяться в опыте чтения.

Figma отдаёт Inter Display как вариативный шрифт по всему приложению. Если вы занимаетесь выбором акцидентной гарнитуры для интерфейса продукта, изучите, как Figma балансирует Inter на мелких насыщенностях UI и Inter Display на крупных размерах заголовков. Дисциплину диапазона насыщенности стоит копировать напрямую.

Чек-лист вариативного шрифта перед деплоем

Прогоните его перед выкаткой вариативного шрифта, и вы поймаете баги, которые кусают в продакшене.

  • Сабсеттинг проверен. Запустите pyftsubset с нужными диапазонами unicode. Убедитесь, что файл латинского сабсета меньше 200KB. Выборочно проверьте, что символы, которые использует ваш контент, присутствуют в результате.
  • Оси задокументированы. Знайте, какие оси отдаёт шрифт, и минимум с максимумом для каждой. Не объявляйте font-weight: 800, если ось заканчивается на 700. Значение молча обрежется, и дизайн будет неверным.
  • Preload настроен. Один <link rel="preload"> на файл сабсета, в <head>, с атрибутом crossorigin, указывающий только на основной латинский файл. Preload файла, который вы не используете, впустую тратит трафик.
  • font-display настроен. В каждом блоке @font-face есть font-display: swap. Убедитесь на вкладке Network в DevTools, что шрифты не блокируют рендеринг критичных ресурсов.
  • Метрики фолбэка подогнаны. Есть блок @font-face для системного фолбэка с рассчитанными size-adjust, ascent-override и descent-override. Проверьте, включив троттлинг Slow 3G в DevTools и посмотрев на сдвиг макета при загрузке. CLS должен быть 0 или около 0.
  • Оси, используемые дизайном, подтверждены. Каждая ось, объявленная в CSS, действительно используется в финальном дизайне. Оси, которые есть в файле шрифта, но не в CSS, всё равно добавляют байты. Если вы не используете ширину, подумайте о сабсеттинге диапазона осей, чтобы срезать эти байты.
  • Оценка Lighthouse проверена. Запустите Lighthouse на продакшен-URL с подключённым шрифтом. Связанные со шрифтом LCP и CLS должны быть зелёными. Если нет, метрики фолбэка неверны или отсутствует preload.
  • CORS-заголовки подтверждены. Вариативным шрифтам, загружаемым с CDN или внешнего origin, нужны заголовки Access-Control-Allow-Origin. Проверьте вкладку Network на ошибки CORS. Сбой CORS приводит к тихому откату на фолбэк-шрифт, который трудно диагностировать в продакшене.

FAQ

Что такое вариативный шрифт и чем он отличается от статического?

Вариативный шрифт — это один файл, содержащий весь диапазон дизайна гарнитуры, управляемый осями вроде насыщенности, ширины, наклона и оптического размера. Статический шрифт — это один снимок с одной насыщенностью и стилем. Практическая разница в том, что вариативный шрифт позволяет использовать font-weight: 350 или плавно анимировать насыщенность в CSS, тогда как статические шрифты допускают только те конкретные значения, которые словолитня решила выпустить отдельными файлами.

Правда ли, что вариативные шрифты улучшают производительность?

Зависит от того, сколько начертаний вы грузите. Если вы отдаёте два статических начертания общим весом 60KB, переход на вариативный шрифт в 180KB ухудшает производительность. Если вы отдаёте пять начертаний общим весом 300KB, переход на вариативный шрифт в 120KB после сабсеттинга — явная победа. Аргумент в пользу производительности вариативных шрифтов реален, но он работает только после порога в три начертания и при правильном сабсеттинге.

Какой вариативный шрифт лучше всего подходит для UI-дизайна?

Inter — самый широко применяемый вариативный шрифт в UI-дизайне. Его ось насыщенности хорошо откалибрована для экрана, он чисто сабсетится, а Figma использует его как продакшен-эталон. Roboto Flex — правильный выбор, когда нужен широкий диапазон осей для адаптивных редакционных макетов. Recursive стоит изучить, если вам нужны и вариативный гротеск, и вариативный моноширинный из одного семейства. Для принципов веб-дизайна, требующих более выразительной акцидентной гарнитуры, Fraunces и Playfair Display оба отдают сильные оси оптического размера и насыщенности.

Как использовать font-variation-settings в CSS?

font-variation-settings — это низкоуровневое свойство для прямой установки осей вариативного шрифта через четырёхбуквенный тег оси и числовое значение: font-variation-settings: 'wght' 450, 'wdth' 85. Для зарегистрированных осей вроде насыщенности и ширины предпочитайте высокоуровневые CSS-свойства (font-weight, font-stretch), потому что они наследуются и композируются корректно. Используйте font-variation-settings только для кастомных осей, у которых нет высокоуровневого CSS-свойства.

Могут ли вариативные шрифты вызвать сдвиг макета?

Да, и они вызывают его вероятнее, чем статические шрифты, потому что файл больше и грузится дольше. Решение — font-display: swap в сочетании с фолбэком с подогнанными метриками. Эта комбинация делает подмену визуально незаметной. Без фолбэка с подогнанными метриками font-display: swap меняет невидимый текст на видимый скачок макета, когда шрифт приходит. Обе проблемы решаются вместе или не решаются вовсе.

Поддерживаются ли вариативные шрифты во всех браузерах?

Вариативные шрифты поддерживаются во всех современных браузерах: Chrome, Firefox, Safari и Edge. Базовая поддержка достаточно надёжна, чтобы вам не нужен был статический фолбэк ради совместимости с браузерами. Доля пользователей на браузере без поддержки вариативных шрифтов для большинства продакшен-сайтов меньше одного процента. Для этого крайнего случая предусмотрите системный шрифт в качестве фолбэка, а не стек статических шрифтов.

Как работает сабсеттинг вариативного шрифта?

Сабсеттинг удаляет из файла шрифта глифы, которые ваш контент никогда не отрисует, с помощью инструмента вроде pyftsubset из Python-библиотеки fonttools. Вы указываете нужные диапазоны символов unicode, и инструмент вычищает всё остальное. Полный вариативный шрифт может содержать 3000 глифов. Сабсет только с латиницей оставляет около 250. Результат — идентичный визуальный вывод для латинского контента примерно при трети размера файла. Полный справочник по командам смотрите в статье глоссария о сабсеттинге.

Сдвиг, который на самом деле открывают вариативные шрифты

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

Архитектура переменных Figma, на которой держатся современные дизайн-системы, естественно ложится на оси вариативного шрифта. Токен font-weight в Figma — это значение оси в шрифте. Соедините хорошо структурированную систему токенов с правильно сабсеттированным вариативным шрифтом, и дизайн-решения будут распространяться от файла дизайна до продакшена без двусмысленности. Добавьте к этому систему цвета OKLCH на состояниях hover, и вы построите продуктовые взаимодействия, которые ощущаются продуманными, а не собранными на скорую руку.

Планка для продакшен-вариативных шрифтов — не «мы выкатили вариативный шрифт». Планка — это правильный сабсеттинг, корректный preload, подогнанные метрики фолбэка и только те оси, которые использует дизайн. Именно этот стандарт отделяет команды, занимающиеся продакшен-типографикой, от команд, занимающихся театром типографики.

Хотите вариативные шрифты, которые весят вдвое меньше и никогда не дёргают страницу? Наймите Brainy, и мы выкатим вам продакшен-стек типографики с правильными осями, правильными сабсетами и рецептом загрузки, который держит Lighthouse зелёным.

Want variable fonts that ship at half the bytes and never jank the page? Brainy ships production typography stacks with the right axes, the right subsets, and the loading recipe that keeps Lighthouse green.

Get Started

More from Brainy Papers

Keep reading