От автора: еще совсем недавно в интернете было столько дискуссий по поводу производительности веб-шрифтов. Доля нестандартных, кастомных шрифтов продолжает расти, но никто не задумывается по поводу их производительности. Если бы вы посидели в интернете с медленным соединением, то вы бы поняли, о чем я говорю.
Стандартный способ использования шрифтов через @font-face может смутить ваших пользователей. В этой статье мы подробно разберем работу @font-face, проблемы, связанные с ним, различные пути увеличения скорости загрузки шрифтов, а также рассмотрим перспективы уменьшения времени загрузки веб-шрифтов в будущем.
Как мы до этого дошли
«Начиная с 1998 года, когда вышел IE4, и далее в марте 2008 по март 2010 годов один за другим «большая пятерка» браузеров — Safari, Firefox, Opera и Chrome – добавляют поддержку @font-face» — //alistapart.com/article/fonts-at-the-crossing. Бум по @font-face пришелся на 2010 год, но тогда еще интернет сильно отличался от сегодняшнего:
Для кроссбраузерной работы необходимо 4 формата шрифта для @font-face: EOT, TTF, WOFF и SVG.
Поддержка этого селектора в мобильных устройствах делалась по остаточному принципу. К примеру, на момент выхода iPhone 4 в 2010 году, мобильный браузер Safari падал при попытке загрузить более одного стиля для веб-шрифта.
Сегодня же по данным сайта caniuse.com numbers поддержка @font-face во всем мире составляет 92.92% и 97.89 в Штатах. По факту для того, чтобы шрифт работал во всех браузерах, хватает и формата WOFF. Но к несчастью, все еще остаются проблемы, которые так и не были решены на ранней стадии развития веб-шрифтов: производительность.
@font-face в браузерах по умолчанию
«В случаях, когда текст загружается раньше, чем шрифта, браузер может отобразить текст запасным шрифтом или прозрачным. Чтобы избежать мигания текста на странице используйте запасной шрифт» — //www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-face-loading
Хотя данный раздел спецификации и не был представлен до 2011 года, но теперь он очень полезен. В 2009 году Firefox и Opera встроили поддержку резервных шрифтов в @font-face: если основной используемый шрифт не успевал загрузиться до отображения страницы, то к тексту применялся запасной шрифт. Однако данный подход смутил множество пользователей (смотрите Firefox bug report), и этот феномен окрестили FOUT, что по-русски значит Мигание Нестилизованного Текста. Множество статей было написано о том, как бороться с МНТ при использовании @font-face. Все это было еще в те времена, когда большинство браузеров просто не отображали текст до конца загрузки шрифтов.
К несчастью, сейчас основной проблемой с @font-face, от которой раньше хотели избавиться, является МСТ или Мигание Скрытого/невидимого Текста. Рассмотрим подробнее на примере:
1 2 3 4 5 6 7 8 9 10 |
@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: url(opensans.woff) format('woff'); } body { font-family: 'Open Sans', 'Arial', sans-serif; } |
Запасной шрифт указан, однако многие браузеры диктуют такой синтаксис следующим образом: текст останется прозрачным пока Open Sans не загрузится или не сохранится в кэш. Во многие webkit браузерах есть задержка в 3 секунды, прежде чем начать отсчет и показать запасной шрифт. На крайне медленных соединениях некоторые браузеры могут ждать от 30 секунды до бесконечности и постоянно мигать текстом.
Ускоряем загрузку веб-шрифтов
У мобильных пользователей точно был опыт использования крайне медленных соединений, типа Edge, 3G и таких, которые Jake Archibald называет «Ложный Wi-Fi»: бесплатный интернет в аэропортах или отелях часто по скорости сравним со старым dial-up соединением. Чтобы исправить этот недуг, нам необходимо загружать @font-face таким образом, чтобы он не мешал отрисовке шрифта.
В то время пока одни опасаются МНТ, самым удачным вариантом с точки зрения производительности будет вариант отложить загрузку своих шрифтов с помощью font-family до тех пор, пока они не станут доступны. Такой подход также имеет смысл на тех сайтах, где основной упор сделан на чтение текста.
Загрузчики шрифтов
Вам понадобится JavaScript, малые изменения могут серьезно увеличить производительность. Ниже я привел краткий список лучших вариантов по загрузку веб-шрифтов на сегодня:
Typekit/Google Web Font Loader, минифицированный до 11Кб
Возможно, вам уже приходилось иметь дело с этим загрузчиком, шрифты хранятся или в Google, или на Typekit. Во время загрузки страницы Web Font Loader сравнивает ширину двух блоков, чтобы определить, готова ли страница для использования вашего шрифта (смотрите код). При асинхронном использовании Web Font Loader, как в примере ниже, страница не блокируется.
1 2 3 4 5 6 7 8 9 10 11 |
<script> WebFontConfig = { typekit: { id: 'xxxxxx' } }; (function(d) { var wf = d.createElement('script'), s = d.scripts[0]; wf.src = '//ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js'; s.parentNode.insertBefore(wf, s); })(document); </script> |
Web Font Loader делает почти всю работу с JavaScript за вас, делает всевозможные проверки и устанавливает классы для каждого типа шрифтов. Обратите внимание: переменная fvd – описание типа шрифта.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
WebFontConfig = { loading: function() {}, active: function() {}, inactive: function() {}, fontloading: function(familyName, fvd) {}, fontactive: function(familyName, fvd) {}, fontinactive: function(familyName, fvd) {} }; .wf-loading .wf-active .wf-inactive .wf-<familyname>-<fvd>-loading .wf-<familyname>-<fvd>-active .wf-<familyname>-<fvd>-inactive |
Font Face Observer, в минифицированном виде 4Кб
Font Face Observer отличный легкий инструмент от Bram Stein. Bram работал на Typekit и были одним из разработчиков Web Font Loader, я просто процитирую его:
«Font Face Observer это маленький @font-face загрузчик, сравнимый с любым веб-сервисом по загрузке шрифтов. Он отслеживает, когда шрифт применяется к странице, и уведомляет вас об этом. Не существует вообще никаких ограничений по поводу того где, когда или как вы будете загружать веб-шрифты. В отличие от Web Font Loader, Font Face Observer использует события прокрутки страницы для определения полной загрузки шрифта, а также минимизирует нагрузку на браузер.»
Хотите подробнее изучить принцип работы, пройдите по ссылке //bramstein.com/writing/detecting-system-fonts-without-flash.html.
1 2 3 4 5 6 7 8 9 |
var observer = new FontFaceObserver('My Family', { weight: 400 }); observer.check().then(function () { console.log('Font is available'); }, function () { console.log('Font is not available'); }); |
Если для вас не проблема написать пару строк кода JavaScript самому, то в таком случае Font Face Observer выполняет все те же функции, что и Web Font Loader. К примеру, ниже представлен скрипт, выполняющий один вызов функции для нескольких семейств шрифтов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
var fontFamilies = { 'Open Sans': [ { weight: 400 }, { weight: 700 } ], 'Open Sans Condensed': [ { weight: 700 } ] } var fontObservers = []; Object.keys(fontFamilies).forEach(function(family) { fontObservers.push(fontFamilies[family].map(function(config) { return new FontFaceObserver(family, config).check() })); }); Promise.all(fontObservers) .then(function() { document.body.classList.add('fonts-loaded'); }, function() { console.log('Fonts not available'); }); |
Посмотреть демо на CodePen.
LocalFont
LocalFont это бесплатный сервис, облегчающий загрузку веб-шрифтов и повторного их использования с локальных носителей. Сайт кодирует ваш шрифт методом base64 и генерирует необходимый для отображения CSS и JS код. Способ очень быстро работает, но я не смог найти информации по поводу сравнения скорости загрузки через сервис или через кэш (//github.com/jaicab/localFont/issues/1). Также, при любом обновлении файлов, вам потребуется придумать способ сброса кэша. Если у вас достаточно времени на проверку ваших веб-шрифтов, я бы не стал использовать локальные носители для хранения кэша.
Боремся с МНТ
Чтобы выбрать резервный шрифт воспользуйтесь, к примеру, таки сервисом //fontfamily.io/.
Снизьте по максимуму рефлоу (повторные построения DOM страницы) в ваших шрифтах, используйте стандартные высоты строк и т.д., все, чтобы ваш шрифт походил на стандартный. Такой подход минимизирует Мигание Нестилизованного Текста в момент переключения на ваш шрифт, особенно на страницах с большими объемами текста. Также ознакомьтесь //www.stateofwebtype.com/#font-size-adjust
Установите временной лимит на применение кастомного веб-шрифта. Во избежании раздражающего переключения шрифта, просто не применяйте ваш шрифт, если он грузится слишком долго.
Когда ваш шрифт загрузился в кэш, на последующих страницах вашего сайта можно избежать проверки готовности шрифта с помощью методик cookie или похожих. Однако в большинстве современных устройств и браузерах скорость извлечения файлов шрифта с локальных носителей или из кэша настолько быстра, что, в принципе, об этом можно вообще не беспокоиться.
Загрузка шрифтов в ближайшем будущем
Нет нужды объяснять, что еще столько всего можно улучшить. К счастью, что у нас есть такие инструменты, как Font Loading API и CSS Font Rendering draft, которые обеспечат нам светлое будущее.
Font Loading API
Новое Font Loading API обращается к @font-face нативным способом, что позволяет избавиться от JS загрузчиков. Данное API уже доступно для Chrome и Opera! На Github у Bram Stein также есть Font Loading полифилл.
1 2 3 4 5 6 7 8 9 |
var f = new FontFace("newfont", "url(newfont.woff)", {}); f.load().then(function (loadedFace) { document.fonts.add(loadedFace); document.body.style.fontFamily = "newfont, serif"; }); document.fonts.ready().then(function() { // все семейства @font-face готовы к применению }); |
CSS Font Rendering Draft
CSS Font Rendering позволит разработчикам контролировать момент отрисовки браузерами шрифта с помощью одного лишь CSS. На данный момент, данный инструмент является частью спецификации Fonts Level 4. Пока что еще слишком рано говорить, когда он будет доступен.
1 2 3 |
@font-face { font-display: auto | block | swap | fallback | optional; } |
Вывод
Стандартное использование @font-face может сильно ударить по производительности сайта, но все же существует множество других способов загрузки веб-шрифтов без блокировки отрисовки текста. И решить эту проблему все легче и легче.
В конечном счете, надеюсь, что после этой статьи вы задумались по поводу производительности загрузки веб-шрифтов на своем сайте. Протестируйте скорость загрузки страниц на webpagetest.org, и решите, что вы можете сделать с @font-face, чтобы увеличить скорость загрузки.