CSS font-display: Майбутнє рендерингу шрифтів у вебі

10 хв. читання
19 листопада 2017

Одним із недоліків використання веб-шрифтів, є те, що у випадку недоступності шрифту на пристрої користувача, його необхідно завантажувати. Це означає, що до того як шрифт стане доступним, браузер повинен вирішити як відобразити будь-який блок тексту, який використовує цей шрифт. І це потрібно зробити таким чином, щоб не вплинути на досвід користування.

З часом, браузери прийняли декілька стратегій для пом'якшення цієї проблеми. Але вони роблять це по-різному і поза контролем розробників, які повинні були придумати шляхи вирішення цих питань.

Вітайте дескриптор font-display для правила @font-face. Ця CSS функція надає можливість стандартизувати таку поведінку і надає більше контролю розробникам.

Використання font-display

Перед тим як зануритись у деталі, коротко розглянемо як можна використовувати font-display у вашому CSS.

Насамперед, font-display не є CSS властивістю, а, як було згадано у вступі, це дескриптор правила @font-face. Це означає, що його потрібно використовувати всередині правила @font-face:

@font-face {
  font-family: 'Saira Condensed';
  src: url(fonts/sairacondensed.woff2) format('woff2');
  font-display: swap;
}

У цьому фрагменті коду я встановлюю значення swap для шрифту Saira Condensed.

Ключовими словами для всіх доступних значень є:

  • auto
  • block
  • swap
  • fallback
  • optional

Початковим значенням для font-display є auto.

У наступних розділах я детально розгляну кожне із цих значень. Але спочатку погляньмо на період часу, який браузер використовує для визначення шрифту, що відображатиметься. Обговорюючи кожне з цих значень, я поясню різні аспекти часової шкали та як вони поводяться для кожного значення.

Часова шкала font-display

В основі цієї функції лежить концепція часової шкали font-display. Час завантаження шрифту, починаючи від запиту і закінчуючи успішним завантаженням або невдачею, можна розділити на три послідовні фази, які визначають, як браузер повинен відобразити текст. Ці три фази такі:

  1. Фаза блокування. У цей час браузер відображає текст із невидимим резервним шрифтом. Якщо викликаний шрифт успішно завантажується, текст рендериться ще раз із цим шрифтом. Невидимий резервний шрифт виступає як порожній заповнювач для тексту. Це зменшує зміни макету при виконанні повторного рендерингу.
  2. Фаза зміни. Якщо потрібний шрифт ще не доступний, використовується резервний шрифт, але цього разу текст відображається. Знову ж таки, як тільки потрібний шрифт завантажиться, його буде використано.
  3. Фаза відмови. Якщо шрифт не стає доступним, браузер не чекає на нього, а на час поточного відвідування сторінки, текст буде відображено за допомогою резервного шрифту. Зауважте, що це не обов'язково означає, що завантаження шрифту переривається; замість цього браузер може продовжити його завантаження, щоб шрифт був готовий до використання під час наступних відвідувань сторінки тим самим користувачем.

Регулювання тривалості таких періодів дає змогу налаштовувати власну стратегію рендерингу тексту. Зокрема, її можна зменшувати до нуля або розширювати до нескінченності. Я покажу як це зробити у наступних розділах.

Але тривалість цих періодів не може явно встановлюватись розробником. Ця можливість була розглянута на ранній стадії специфікації, але була виключена. Натомість, як зазначено в попередньому розділі, надано набір визначених значень ключових слів, які можуть обробляти більшість випадків використання.

Подивімося, як кожне з цих ключових слів керує процесом завантаження та відображення шрифтів.

font-display: auto

Це значення вказує браузеру прийняти поведінку відображення шрифту за замовчуванням. Часто ця стратегія є схожою до наступного значення, block.

font-display: block

З цим значенням, після короткої фази блокування (специфікація рекомендує 3 секунди), фаза зміни розширюється до нескінченності. Це означає, що за цієї обставини фаза відмови відсутня.

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

Ви можете спостерігати за цією поведінкою у наступному відео, яке використовує просту тестову сторінку, яка містить особливий веб-шрифт для заголовка:

{@vimeo:https://vimeo.com/243064030}

На початку завантаження сторінки заголовок невидимий, але він присутній у DOM. Приблизно через три секунди, якщо шрифт ще не доступний, текст стає видимим із резервним шрифтом. У демонстрації я відтворюю умови слабкого інтернет-з'єднання, використовуючи функцію дроселювання (throttling) пропускної здатності мережі у Chrome DevTools. Нарешті, коли шрифт вдається завантажити, заголовок буде повторно відображено з ним.

font-display: swap

З цим значенням фаза блокування згортається до 0, а фаза зміни розширюється до нескінченності. Тому тут також відсутня фаза відмови.

Іншими словами, браузер не чекає на шрифт, а замість цього негайно відображає текст із резервним шрифтом; тоді, коли шрифт є доступним, текст з ним повторно рендериться.

Перевірмо це:

{@vimeo:https://vimeo.com/243064236}

font-display: fallback

Це перше значення, яке включає фазу відмови. Після дуже короткої фази блокування (рекомендовано 100 мс), фаза зміни тепер має коротку тривалість (рекомендовано 3 с). В результаті, якщо потрібний шрифт не буде готовий наприкінці цього періоду, на час відвідування сторінки текст відображатиметься за допомогою резервного шрифту. Це дозволяє не відволікати користувача пізньою заміною макету.

У цьому першому відео нижче шрифт завантажується більш ніж 6 секунд, тому він ніколи не змінюється:

{@vimeo:https://vimeo.com/243064310}

У наступному відео шрифт завантажується швидше, перш ніж закінчиться фаза зміни, тому шрифт використовується, як очікувалося:

{@vimeo:https://vimeo.com/243064555}

font-display: optional

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

Запропоновано такі альтернативи:

  • requires для block
  • important для swap
  • preferable для fallback

Але значення optional залишиться незмінним. Це значення добре передає суть поведінки, яку воно викликає. У цьому випадку шрифт вважається необов'язковим для відтворення сторінки, по суті, кажучи браузеру: якщо шрифт готовий, використай його, інакше він не має значення, продовжуй з резервним шрифтом; шрифт може бути готовим для майбутніх відвідувань сторінки.

З цим значенням, часова шкала font-display має коротку фазу блокування (у специфікації рекомендовано 100 мс) та фазу зміни з нульовою тривалістю. Отже, фаза відмови йде одразу після фази блокування, що означає, якщо шрифт не готовий відразу, його не буде використано під час цього відвідування сторінки. Але шрифт може бути повністю завантажений у фоновому режимі, і він стане доступним для негайного відтворення на майбутніх завантаженнях сторінки.

Але тут слід зазначити, що, особливо в умовах слабкого інтернет-з'єднання, користувацький агент може скасувати або навіть не розпочинати завантаження шрифтів. Це має на меті виключити зайвий вплив на якість мережевого з'єднання. Тому сайт все ще можна використовувати, але шрифт не буде доступний під час майбутніх завантажень сторінки.

У наведеному нижче відео, тестова сторінка завантажується без дроселювання мережі. Шрифт завантажується швидко, але лише після короткої фази блокування, тому текст відображається за допомогою резервного шрифту протягом усього періоду відвідування.

{@vimeo:https://vimeo.com/243064744}

У наступному відео сторінка перезавантажується в тих самих мережевих умовах, але на цей раз увімкнено кеш, щоб імітувати другий візит:

{@vimeo:https://vimeo.com/243064793}

І ось результат, заголовок відображається з бажаним веб-шрифтом.

Перш ніж продовжувати, відзначте надзвичайно коротку тривалість (близько 100 мс) фази block при використанні значень fallback та optional.

Я насправді дивувався, чому фаза блокування зменшується до нуля, коли використовується font-display: swap, замість того, щоб використовувати такий же короткий інтервал, як для optional. Виявляється, що є відкрите питання на GitHub репозиторії специфікації, для того щоб змінити тривалість фази блокування swap-значення на таку ж як в інших.

Про резервний шрифт

У тексті вище я декілька разів згадував про резервний шрифт. Але ж звідки він походить?

Резервний шрифт – перший доступний шрифт у стеку шрифтів, визначений за допомогою властивості font-family у відповідному елементі.

Наприклад, на тестовій сторінці значення font-family для заголовка є:

h1 {
  font-family: 'Saira Condensed', Arial, "Helvetica Neue", Helvetica, sans-serif;
}

Це можна перевірити (див. відео вище для optional), наприклад, на комп'ютері з Windows, який використовує Arial як шрифт для відображення.

Підтримка

На час написання статті, рівень підтримки дескриптора font-display наступний:

  • Chrome підтримує його з версії 60
  • Opera підтримує з версії 47
  • Для Firefox він у розробці та є доступним з вендорним префіксом з версії 46
  • Щодо Safari, то згідно зі статусом Webkit платформи – він у розробці
  • Немає жодних ознак того, що Microsoft Edge буде підтримувати його в будь-який час незабаром. Існує квиток на сайті Microsoft Edge Developer Feedback, де можна проголосувати за реалізацію цієї функції.

Будь ласка, зверніться до сайту caniuse.com для отримання найновішої інформації про підтримку.

Варто згадати, що підтримку font-display не можна перевірити за допомогою функціональних запитів, оскільки, як зазначено вище, це не властивість CSS, а дескриптор шрифту. У цьому питанні на GitHub ви знайдете обговорення того, як правильно визначити цю функцію.

Як тільки було виявлено, що font-display не підтримується, існує декілька альтернативних варіантів, які можна використати, але це не стосується цієї статті. У статті Зака Летермана «Комплексний довідник зі стратегій завантаження шрифтів» представлено вичерпний огляд доступних рішень.

Використання з Google Fonts

Можливо ви помітили, що шрифт, який використовується на демонстраційній сторінці, – з Google Fonts, але він не завантажується звичайним способом, тобто посиланням на таблицю стилів, надану постачальником шрифтів. Замість цього я просто скопіював URL-адресу шрифту, знайденого в цій таблиці стилів, і використав цю адресу в моєму користувацькому правилі @font-face. Мені довелося це зробити, тому що, як видно з розділу використання, font-display повинен бути вказаний в правилі @font-face.

Чи є кращий спосіб підключення до Google Fonts? Чи будуть Google Fonts та інші компанії-розробники шрифтів підтримувати font-display?

Є відкрите питання на GіtHub репозиторії Google Fonts, де це обговорюється. Додайте +1, щоб показати свою зацікавленість у цьому питанні!

Також варто зазначити, що CSS Fonts Module Level 4 пропонує використовувати font-display як дескриптор для @font-function-values, щоб дозволити розробникам встановлювати політику відображення для правил @font-face, які не знаходяться безпосередньо під їхнім контролем. Але це ще не впроваджено жодним користувацьким агентом.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація