x
 
Александр
21 декабря 2017
Советы почтой каждую неделю
Пожалуйста, получите наше письмо, чтобы подтвердить свой адрес:
Вы подписаны на «Советы за неделю»:

Василию Половнёву: как быстро и без миганий загружать веб-шрифты?


Это зависит от задачи. Расскажу, как мы решаем эту проблему в книгах бюро.

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

Долгое время мы загружали веб-шрифты, кодируя их в Base64 и встраивая прямо в ЦСС. Это медленно: шрифты весят на 30% больше, плюс уходит время на декодирование. Когда мы вынесли шрифты из ЦСС и стали загружать их в WOFF2 по HTTP/2, время до первой отрисовки сократилось на треть.

А чтобы при следующем открытии шрифты не грузились заново, явно кешируем их навечно:

cache-control:max-age=315360000
expires:Thu, 31 Dec 2037 23:55:55 GMT

Анти-паттерн для веб-шрифтов: Data-URI

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

<head>
  <title>...</title>

  <link rel="preload" as="font" type="font/woff2"
    href="https://fonts.bureau.ru/1.6/bureausans-regular.woff2"
    crossorigin>

  <link rel="preload" as="font" type="font/woff2"
    href="https://fonts.bureau.ru/1.6/bureausans-bold.woff2"
    crossorigin>
</head>
После включения предзагрузки шрифтов, время до первой отрисовки «Типографики и вёрстки» уменьшилось в среднем на секунду

Чтобы шрифты не мигали, мы дожидаемся их загрузки и готовности. Для этого в книгах есть «пробники» — элементы с заданным шрифтом и требуемой шириной.

Например, мы знаем, что слово mmm, набранное Бюросансом с кеглем в 100 пикселей, имеет ширину 238 пикселей на экране. То же слово, набранное системным шрифтом, — 250 пикселей. Значит, если ширина элемента с текстом mmm равна 238 пикселям, шрифт загружен и готов к использованию.


<style>
.fontChecker {
  position: fixed;
  z-index: -1;
  font-size: 100px;
  opacity: 0;
}

.fontChecker::before {
  content: 'mmm';
}
</style>

<div
  style="font-family: Bureausans;"
  data-min-width="237"
  data-max-width="240"
  class="fontChecker js__fontChecker">
</div>
Небольшой разброс нужен для ретины-неретины, где ширина и начертание немного меняются

Перед запуском книга ждёт, пока размеры всех пробников не попадут в требуемые:

let fontCheckInterval

// Как часто проверяем пробники
const FONT_CHECK_INTERVAL = 100

// Максимальное время ожидания шрифтов
const MAX_FONTS_WAIT = 4000

const isFontLoaded = (font) => {
  const probeWidth = font.$el.width()

  return probeWidth >= font.minWidth && probeWidth <= font.maxWidth
}

const onFontsReady = (callback) => {
  const fonts = $('.js__fontChecker').map((_, el) => {
    const $el = $(el)

    return {
      $el: $el,
      minWidth: +$el.attr('data-min-width'),
      maxWidth: +$el.attr('data-max-width'),
    }
  }).get()

  let timeSpent = 0

  fontCheckInterval = setInterval(function() {
    const allFontsReady = fonts.every(isFontLoaded)

    // Если все шрифты уже готовы или
    // мы так и не дождались их загрузки,
    // отрисовываем страницу
    if (allFontsReady || timeSpent > MAX_FONTS_WAIT) {
      clearInterval(fontCheckInterval)
      callback()
    }

    timeSpent += FONT_CHECK_INTERVAL
  }, FONT_CHECK_INTERVAL)
}

// onFontsReady(initApp)
Первая версия опиралась на document.fonts.ready. К сожалению, в Сафари он срабатывает слишком рано: когда браузер уже загрузил шрифты, но ещё не применил их к странице

Ещё по теме

Для чего стоит использовать предварительную загрузку

P. S. Это был совет о веб-разработке. Хотите знать всё о коде, тестах, фронтенд-разработке, цеэсэсе, яваскрипте, рельсах и джейде? Присылайте вопросы.
Вёрстка и прототипирование — дисциплина Школы дизайнеров. Набор открыт до 13 августа или пока есть свободные места.
 

Поделиться
Отправить

Цель рубрики — обсуждение вопросов дизайна всех видов, текста в дизайне и взаимоотношений дизайнеров с клиентами.

Мы публикуем комментарии, которые добавляют к уже сказанному новые мысли и хорошие примеры. Мы ожидаем, что такие комментарии составят около 20% от общего числа.

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

Вот такой веб 2.0.

Как бороться с багами? Часть шестая: изолировать 4 Как бороться с багами? Часть пятая: повторить Почему вы используете jQuery для хождения по дереву и управления событиями? 2




Недавно всплыло

2 4 Как научиться не принимать всё так близко к сердцу и не сливать свою энергию при общении с клиентами? 10 4