Перейти до вмісту

Шрифт

гарнітура у файлі, який завантажує сторінка

Що це таке

Шрифт, або вебшрифт, коли його віддає сайт, а в специфікаціях CSS font face, — це файл із намальованими літерами одного дизайну в одній насиченості й одному стилі разом із таблицями, які підказують програмам, який малюнок відповідає якому символу і з якими проміжками їх ставити.

Типографи розрізняють дизайн і його файли. Ubuntu — це гарнітура; Ubuntu Light і Ubuntu Bold Italic — її накреслення, кожне в окремому файлі. CSS тримає той самий поділ. Родина шрифтів об’єднує накреслення під однією назвою, а кожне правило @font-face описує одне накреслення: до якої родини воно належить, звідки його брати, яку насиченість і стиль воно покриває, які символи може намалювати і що показувати, поки воно завантажується.

@font-face {
    font-family: "Reading Serif";
    src:
        local("Reading Serif Regular"),
        local("ReadingSerif-Regular"),
        url("/fonts/reading-serif-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

body {
    font-family: "Reading Serif", Georgia, serif;
}

Властивість font-family на елементі — це список, який читають зліва направо. Специфікація обирає родину й накреслення для кожного символу у фрагменті тексту: бере перше накреслення, що має потрібну насиченість і стиль і містить гліф для цього символу. Тож один рядок може бути набраний двома шрифтами, коли першому бракує літери, а загальна назва в кінці списку, serif, sans-serif, monospace чи system-ui, гарантує, що решту завжди візьме якийсь встановлений шрифт.

У вебі файл майже завжди має формат WOFF2: ті самі контури й таблиці OpenType чи TrueType, перепаковані для передавання й стиснуті Brotli. Усередині таблиця cmap зіставляє кожен код символу з гліфом, а інші таблиці несуть числа, потрібні рушію верстки: ascent, descent і line gap, а також де лежить підкреслення і яка його товщина. Ці числа визначають висоту рядка й проміжки не менше, ніж форми літер визначають вигляд.

Чому це важливо

Кожна насиченість і кожен стиль — окреме завантаження. Дизайн зі звичайним, курсивним і жирним текстом ставить три файли між читачем і текстом, набраним ними, і кожен додає байтів до першого відвідування. Дескриптор unicode-range дає змогу розділити родину на частини за системою письма, а специфікація забороняє браузерові завантажувати частину для символів поза її діапазоном, тож сторінка отримує лише ті частини, яких потребує її текст.

Текст у вебшрифті можна намалювати лише після того, як прибуде файл, тож браузерові потрібне правило на час очікування. Його задає дескриптор font-display. Для block специфікація рекомендує період блокування в 3 секунди, протягом якого текст розміщено, але намальовано невидимим. Для swap період блокування становить 100 мс або менше, резервний шрифт з’являється майже одразу, а вебшрифт заміняє його, щойно надійде. Для fallback вікно заміни коротке, рекомендовано 3 секунди, після чого сторінка лишає резервний шрифт. Для auto вирішує браузер, і багато браузерів поводяться з ним як із block.

Важить і те, де лежить файл. Запити шрифтів ідуть через CORS, тож шрифт з іншого походження (origin) завантажується лише тоді, коли той сервер це дозволяє, а кожен запит до сервера іншої компанії повідомляє їй адресу читача й те, на якому сайті він перебуває. Шрифти з власного хоста сайту прибирають і зайве з’єднання, і спостерігача.

Шрифт — це програмне забезпечення під ліцензією. SIL Open Font License дозволяє використовувати, вивчати, змінювати й поширювати шрифти, доки їх не продають окремо, і забороняє зміненій версії брати зарезервовану назву шрифту без дозволу. Шрифт, куплений для друку, може мати інші умови для вебу, тож прочитайте ліцензію, перш ніж файл потрапить на сервер.

Покриття — останнє питання. Шрифт малює лише ті символи, які перелічує його cmap. Більша частина кирилиці лежить у діапазоні U+0400–045F, але українська літера ґ живе в U+0490–0491, тож підмножина чи діапазон, складені для російського тексту, віддають її наступному резервному шрифту.

Як це виглядає на практиці

Сторінка подяк сайту перелічує те, що доходить до браузера читача, як п’ять речей, і три з них — вебшрифти. Ubuntu від Dalton Maag, створений для Canonical, поширюється за ліцензією Ubuntu Font Licence. Ubuntu Mono, моноширинне накреслення тієї самої родини, набирає код. Shantell Sans, створений на основі почерку художниці Shantell Martin, яка пише маркером, поширюється за ліцензією SIL Open Font License, і ним написано нотатки на полях. Усі три приходять із власного сервера сайту, і сторінка пояснює чому: вебшрифт із чужого CDN — це третя сторона, яка спостерігає, як ви читаєте. Ubuntu Mono і Shantell Sans завантажуються лише на тих сторінках, де є код або нотатка на полях.

Як розділити одну гарнітуру за системою письма, розповідає нотатка про підкреслення в Safari. Сайт віддає Ubuntu шістьма частинами, три насиченості латиницею і три кирилицею, і кожна частина оголошує символи, які покриває, тож англійські й данські сторінки завантажують три латинські файли й жодного кириличного, а українські навпаки. Усі шість мали одну назву родини, а в Safari накреслення з нелатинським діапазоном погіршує skip-ink, проміжок, який підкреслення лишає навколо нижнього виносного елемента, для кожного символу своєї родини, зокрема й латинського тексту. Коли три кириличні оголошення видалили під час виконання, виміряні проміжки зросли з 1,8/1,0/1,0px до 4,5/11,0/5,0px. Виправлення дало кириличним накресленням власну назву родини й поставило її в стек після Ubuntu: три перейменовані оголошення й один запис у стеку, Chrome без змін, а українська й далі набрана Ubuntu з ідентичною шириною. Та сама нотатка показує, як сильно різняться власні числа шрифту: Ubuntu оголошує товщину підкреслення 0,056em для Light, 0,020em для Medium і 0,120em для Bold.

Цільова сторінка перед власним git-сервером компанії була копією дизайну головного сайту, яку підтримували вручну, і кожна знайдена між ними відмінність виявилася випадковістю, а не рішенням. Дві з п’яти стосувалися шрифтів: оголошення шрифту, яке на будь-якій машині зі встановленою гарнітурою зводило дві насиченості до однієї, і насиченість, для якої не постачався шрифт. Жодної з п’яти не видно на знімку екрана. Копію видалено, і тепер цільову сторінку збирають шаблони самого головного сайту.

Де виникають проблеми

  • Текст невидимий, поки файл завантажується. За block, а часто й за auto, повільне з’єднання показує зверстану сторінку без жодного слова аж до кінця періоду блокування. Використовуйте swap для основного тексту й попередньо завантажуйте один-два файли, потрібні першому екрану. Попереднє завантаження шрифту вимагає атрибута crossorigin навіть для файла з того самого походження, бо воно має збігтися із запитом CORS, який заміняє.
  • Сторінка підстрибує, коли прибуває шрифт. Резервний шрифт з іншою шириною і висотою рядків розриває рядки в інших місцях, і заміна їх переверстує. Специфікація радить резервні шрифти з метриками, близькими до метрик вебшрифту. Де такого немає, накреслення local() для резервного шрифту з ascent-override, descent-override і line-gap-override вирівнює його вертикальні метрики, тож заміна змінює форми літер, а не макет.
  • Жирний і курсив, яких ніхто не малював. Коли родина не має жирного накреслення, браузер може потовщити звичайне, а коли немає курсиву, може його нахилити. Штрихи розпливаються, а прямі літери хиляться. Постачайте кожне накреслення, яке використовує дизайн, або задайте font-synthesis значення none, щоб відсутнє накреслення під час перевірки проявилося як прямий текст звичайної насиченості, а не підробка.
  • local() приймає накреслення, а не родину. Назва всередині local() відповідає одному накресленню за його повною назвою або назвою PostScript. Якщо написати там назву родини для кожної насиченості, вона може збігтися з одним встановленим накресленням для всіх, і жирний відобразиться звичайним саме на тих машинах, де родину встановлено. Називайте кожне накреслення обома способами або пропустіть local().
  • Відсутній гліф змішує гарнітури. Накреслення, якому бракує символу, передає його наступній родині, тож одне слово може показати два дизайни. Надто вузько вирізана підмножина робить те саме з цілою системою письма. Перевіряйте покриття на тексті, який сайт справді публікує, кожною мовою, якою він публікує.

Що почитати далі

  • CSS Fonts Module Level 4 — @font-face, алгоритм зіставлення, unicode-range, font-display і керування синтезом.
  • WOFF File Format 2.0 — як шрифти OpenType і TrueType пакують і стискають для вебу.
  • OpenType cmap table — таблиця, що визначає, які символи шрифт може намалювати.
  • SIL Open Font License — сама ліцензія з умовами щодо копій, змінених версій і зарезервованих назв.
  • WebKit bug 255159 — звіт про skip-ink підкреслень у Safari, на якому ґрунтується нотатка сайту.

Словник