JavaScript библиотеки для работы со шрифтами: полное руководство

Раздел: Веб-разработка -> Библиотеки шрифтов

Библиотеки шрифтов в JavaScript: обзор инструментов

Как загрузить пользовательский шрифт динамически и гарантировать его готовность перед отрисовкой текста?

Основное решение в современных браузерах - использование встроенного FontFace API. Оно позволяет загружать шрифты из внешних источников и управлять их состоянием без дополнительных библиотек.

// Создание объекта FontFace
const myFont = new FontFace('MyCustomFont', 'url(/fonts/myfont.woff2)');

// Загрузка шрифта
myFont.load().then(function(loadedFace) {
  // Добавление в набор доступных шрифтов
  document.fonts.add(loadedFace);
  console.log('Шрифт загружен и готов к использованию');
}).catch(function(error) {
  console.error('Ошибка загрузки шрифта:', error);
});

Fonts js (fonts js библиотека)

Пошаговое объяснение: конструктор принимает имя семейства и URL (или массив URL). Метод load() возвращает Promise, который разрешается после полной загрузки. После вызова document.fonts.add() шрифт становится доступным для CSS.

Типичная проблема: ошибка CORS при загрузке шрифта с другого домена. Сервер должен отправлять заголовок Access-Control-Allow-Origin: * (или ваш домен). В противном случае браузер заблокирует загрузку, и Promise завершится с ошибкой.

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

Вариант 1: FontFaceObserver - простая обёртка для Promise

Эта библиотека создана для тех случаев, когда нужно отслеживать загрузку шрифтов, объявленных в CSS, без создания объектов FontFace вручную.

// Установка: npm install fontfaceobserver
import FontFaceObserver from 'fontfaceobserver';

const observer = new FontFaceObserver('Open Sans', { weight: 400 });

observer.load(null, 10000).then(function() {
  document.documentElement.classList.add('fonts-loaded');
  console.log('Open Sans загружен');
}).catch(function() {
  console.warn('Open Sans не загрузился за 10 секунд');
});

Пояснение: конструктору передаётся имя шрифта (как указано в CSS). Вторым параметром можно передать дескрипторы (weight, style и т.д.). Метод load() принимает текст для проверки (или null) и таймаут в миллисекундах. После загрузки можно добавить класс для отображения, чтобы избежать FOUT (Flash of Unstyled Text).

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

Решение: точно указывать имя семейства, включая регистр и пробелы. Для проверки можно сначала вывести список загруженных шрифтов через document.fonts.keys().

Вариант 2: Web Font Loader от Google (Typekit) - универсальный загрузчик

Библиотека, позволяющая загружать шрифты из различных источников (Google Fonts, Typekit, самописные). Подходит для проектов, где используются внешние сервисы.

// Подключение через CDN
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.28/webfont.js"></script>
<script>
  WebFont.load({
    google: {
      families: ['Roboto:300,400,700', 'Lato']
    },
    custom: {
      families: ['MyFont'],
      urls: ['/css/myfont.css']
    },
    active: function() {
      console.log('Все шрифты загружены');
    },
    inactive: function() {
      console.warn('Не удалось загрузить некоторые шрифты');
    }
  });
</script>

Объяснение: конфигурация содержит разделы для разных провайдеров. Колбэки active и inactive вызываются после завершения загрузки всех шрифтов. Библиотека автоматически добавляет классы в html (например, .wf-active, .wf-inactive), что удобно для стилей.

Проблема: библиотека сама не загружает файлы шрифтов, а полагается на уже подключённые CSS (для Google Fonts - встроенный лист). Если ссылка на CSS неверна, шрифты не загрузятся.

Решение: всегда проверять наличие CSS-файла или правильность API-ключа для Typekit. Для кастомных шрифтов указывать корректный URL на CSS с объявлением @font-face.

Вариант 3: CSS Font Loading API (событие document.fonts.ready)

Если шрифты уже объявлены в CSS через @font-face, можно дождаться их полной загрузки с помощью встроенного события document.fonts.ready.

document.fonts.ready.then(function() {
  document.body.classList.add('fonts-ready');
  console.log('Все шрифты, объявленные в CSS, загружены');
});

// Альтернатива: проверка конкретного шрифта
document.fonts.load('1em Open Sans').then(function() {
  console.log('Open Sans загружен (размер 1em)');
});

Пояснение: document.fonts.ready возвращает Promise, который разрешается, когда все шрифты, указанные в CSS, загружены (или отклонены). Метод load() загружает шрифт с заданным размером и возвращает Promise.

Проблема: если какой-то шрифт не загрузится, Promise всё равно разрешится (некоторые браузеры могут выдавать ошибку). Также API не поддерживается в IE11 и старых версиях браузеров.

Решение: использовать полифилл или комбинировать с FontFaceObserver для обратной совместимости.

Расширенные примеры работы со шрифтами через JavaScript

Пример 1: Загрузка нескольких шрифтов с разными начертаниями через FontFace API

Пример
async function loadFonts() {
  const fontConfigs = [
    { name: 'Roboto', weight: 300, url: '/fonts/Roboto-Light.woff2' },
    { name: 'Roboto', weight: 400, url: '/fonts/Roboto-Regular.woff2' },
    { name: 'Roboto', weight: 700, url: '/fonts/Roboto-Bold.woff2' },
    { name: 'Roboto', style: 'italic', weight: 400, url: '/fonts/Roboto-Italic.woff2' }
  ];

  const fontPromises = fontConfigs.map(config => {
    const font = new FontFace(config.name, `url(${config.url})`, {
      weight: config.weight,
      style: config.style || 'normal'
    });
    return font.load().then(() => document.fonts.add(font));
  });

  try {
    await Promise.all(fontPromises);
    console.log('Все начертания Roboto загружены');
  } catch (error) {
    console.error('Ошибка загрузки одного из шрифтов:', error);
  }
}
loadFonts();
Результат: в консоли появится сообщение об успешной загрузке, либо ошибка с указанием проблемного шрифта. После этого можно использовать шрифт в CSS как `font-family: 'Roboto', sans-serif;`.

Пример 2: Динамическое применение шрифта к элементу после загрузки (с использованием FontFaceObserver)

Пример
import FontFaceObserver from 'fontfaceobserver';

function applyFontToElement(element, fontFamily, fallback) {
  const observer = new FontFaceObserver(fontFamily);
  observer.load(null, 5000).then(() => {
    element.style.fontFamily = fontFamily;
    element.textContent = 'Текст отображается шрифтом ' + fontFamily;
  }).catch(() => {
    element.style.fontFamily = fallback + ', serif';
    element.textContent = 'Шрифт не загрузился. Используется запасной.';
  });
}

const header = document.getElementById('dynamic-font-header');
applyFontToElement(header, 'Playfair Display', 'Georgia');
Результат: если шрифт Playfair Display загружен за 5 секунд, заголовок отобразится им. Если нет - применится Georgia.

Пример 3: Web Font Loader с кастомными шрифтами и таймаутом

Пример
WebFont.load({
  custom: {
    families: ['MySansFont', 'MySerifFont'],
    urls: ['/path/to/mysans.css', '/path/to/myserif.css']
  },
  timeout: 7000,
  active: function() {
    document.querySelector('.status').textContent = 'Шрифты загружены';
    document.body.style.fontFamily = 'MySansFont, sans-serif';
  },
  inactive: function() {
    document.querySelector('.status').textContent = 'Ошибка загрузки, используем системные';
  }
});
Результат: на странице появится индикатор статуса. При успехе шрифт применяется, при неудаче - нет.

Пример 4: Отслеживание загрузки каждого шрифта индивидуально через CSS Font Loading API

Пример
async function checkFonts() {
  const fonts = document.fonts;
  for (const fontFace of fonts) {
    // fontFace.status может быть 'unloaded', 'loading', 'loaded', 'error'
    console.log(`Шрифт ${fontFace.family} (${fontFace.weight}): ${fontFace.status}`);
  }

  // Дожидаемся конкретного шрифта
  try {
    await document.fonts.load('bold 16px/1.5 "Open Sans"');
    console.log('Open Sans bold загружен');
  } catch (e) {
    console.warn('Ошибка загрузки Open Sans bold');
  }
}
checkFonts();
Результат: в консоли последовательно выводится состояние каждого шрифта, а затем сообщение об успехе или ошибке.

Пример 5: Обработка FOUT с помощью запасного шрифта и переключения классов

Пример
const fontObserver = new FontFaceObserver('Ubuntu');

// Начальный стиль с запасным шрифтом
const body = document.body;
body.style.fontFamily = 'Arial, sans-serif';

fontObserver.load(null, 3000).then(() => {
  // После загрузки переключаем на Ubuntu
  body.style.fontFamily = 'Ubuntu, sans-serif';
  body.classList.add('custom-font-loaded');
}).catch(() => {
  // Оставляем Arial, но добавляем класс-индикатор
  body.classList.add('font-load-failed');
});
Результат: текст сначала отображается шрифтом Arial, затем после загрузки Ubuntu заменяется. Если загрузка не удалась, остаётся Arial с классом для возможной стилизации.

Fonts JS библиотека - comments

En
Fonts js (javascript)