Загруженный шрифт может оставаться неиспользованным, если CSS выбирает другое начертание, текст выходит за пределы его покрытия или время его отображения уже истекло. На Mac сначала проверьте, какой шрифт фактически отображает одну надпись, а затем проследите цепочку выбора и загрузки в обратном направлении.
Это руководство предназначено для тех, кто обслуживает веб-страницу, видит успешный запрос шрифта, но всё равно отображается текст резервным шрифтом. Для проверки используйте Chrome в macOS. Условная надпись Panel 204 и название семейства Sample Sans ниже иллюстрируют диагностику и не относятся к какому-либо конкретному сайту.
Что на самом деле подтверждает успешная загрузка?
Разделите диагностику на четыре отдельных вопроса: был ли получен ресурс? Зарегистрировано ли пригодное начертание? Выбрал ли CSS это начертание для данных символов? Отобразил ли его рендерер? Предварительная загрузка шрифта запускает раннюю загрузку; само её наличие не показывает, какой шрифт используется для видимого текста. MDN: rel="preload"
Подбор шрифтов выполняется для текста, а не просто для загруженных файлов. Браузер учитывает запрошенные семейства и свойства шрифта, а затем проверяет поддержку символов. Поэтому в одной надписи могут использоваться несколько шрифтов, а загрузка шрифта из-за другого фрагмента страницы мало что говорит о целевой надписи. W3C: Модуль CSS Fonts, уровень 4, подбор шрифтов
Используйте эту таблицу решений, чтобы выбрать следующую проверку. Это диагностическая подсказка, основанная на документированных этапах загрузки и подбора, а не сводка измеренных результатов браузера.
| Наблюдение | Следующая проверка | Что помогает различить |
|---|---|---|
| Вычисленное семейство отличается от нужного | Найдите победившее объявление CSS | Проблема каскада или селектора |
| Вычисленное семейство правильное, отображаемый шрифт отличается | Проверьте дескрипторы начертания и покрытие символов | Проблема выбора или подстановки |
| JavaScript сообщает, что начертание загружено, но его нет в наборе шрифтов документа | Проверьте код регистрации | Загрузка без регистрации |
| После перезагрузки шрифт появляется, но при первом посещении отсутствует | Проверьте font-display и время загрузки |
Поведение окна отображения |
| Обычный текст отображается правильно, а текст на canvas не меняется | Проверьте порядок отрисовки и настройки шрифта canvas | Отдельная операция рисования |
Какой шрифт фактически отображает целевую надпись?
На затронутой странице нажмите Command + Shift + C и выделите текст. В панели Elements выберите наименьший элемент, содержащий эту надпись. Откройте Computed, затем прокрутите до раздела Rendered Fonts. В документации Chrome этот раздел указан как место для проверки шрифтов, используемых при отображении текста. Chrome DevTools: Справочник по возможностям CSS, Chrome DevTools: Применение других эффектов
Запишите отображаемое начертание и укажите, получен ли его ресурс локально или из сети. Также запишите вычисленные значения font-family, font-weight и font-style. Вычисленное семейство — это запрошенный стек; результат Rendered Fonts показывает, какой шрифт предоставил глифы. Одного лишь сходства внешнего вида недостаточно: два начертания могут выглядеть похоже. Chrome DevTools: Что это за шрифт?
Если нужное начертание используется для затронутого текста, исследуйте конкретное различие во внешнем виде, например насыщенность или функции шрифта. Если его нет, продолжайте проверку ниже. При тестировании сохраняйте исходный текст и размер области просмотра, чтобы результаты можно было сравнить.
Запрашивает ли эффективный CSS нужное начертание?
В Computed проверьте действующие свойства шрифта, затем найдите их объявления в Styles. Chrome различает эти панели: Styles показывает и перекрытые объявления, а Computed — фактически применённые значения. Если карточка содержит несколько надписей, проверьте дочерний элемент с текстом: объявление шрифта для родителя не доказывает, что оно применяется к дочернему элементу. Chrome DevTools: Справочник по возможностям CSS
Проверьте выигравшее сокращённое свойство font и отдельные свойства. Например, font: 16px sans-serif выбирает обобщённое семейство и сбрасывает неуказанные компоненты сокращённой записи, включая насыщенность и стиль. Оно также сбрасывает такие свойства, как font-feature-settings и font-variation-settings. Исправьте объявление, которое отвечает за неожиданное значение, и проверьте результат. MDN: font
Затем сравните запрошенное семейство с дескриптором font-family в соответствующем правиле @font-face. Этот дескриптор задаёт имя семейства CSS, по которому ссылаются на начертание; имя файла не является именем, которое нужно указывать в стеке шрифтов элемента. Проверьте правило, переданное браузеру, включая src, насыщенность, стиль и любые объявленные диапазоны. MDN: @font-face
Для переменного шрифта поддерживаемый диапазон насыщенности можно задать двумя значениями, тогда как для статического начертания может быть указано одно значение. Настройте дескрипторы так, чтобы они точно описывали предоставленный ресурс. Несоответствие стоит проверить, но оно не обязательно объясняет подстановку: при подборе шрифта учитываются альтернативы, если точное начертание недоступно. MDN: @font-face, W3C: Подбор начертаний шрифта
Может ли локальный шрифт иметь приоритет?
Проверьте src на наличие альтернативы local(). Если этот шрифт установлен на Mac, браузер может использовать локальную копию, пока отдельно предварительно загруженный веб-шрифт остаётся неиспользованным. Чтобы изолировать это условие в Chrome, откройте панель Rendering, включите Disable local fonts и перезагрузите страницу. Сравните Rendered Fonts до и после, затем восстановите настройку. Эта проверка касается источников local() в правилах @font-face. Chrome DevTools: Применение других эффектов
Было ли начертание загружено и зарегистрировано в нужном документе?
Начертание, созданное с помощью new FontFace(), может загрузиться до добавления в набор шрифтов. Для отображения в документе его нужно добавить в document.fonts. Проверьте оба действия в коде загрузки приложения: одного успешного завершения промиса загрузки начертания недостаточно для регистрации. MDN: API загрузки шрифтов CSS
Следующий законченный диагностический фрагмент для консоли выводит список начертаний, зарегистрированных в текущем документе. Запустите его в контексте консоли затронутой страницы. Он читает набор, не запуская загрузку и не меняя стили; при этом он не определяет, какие глифы отображаются. Зависимое от браузера поведение этого кода здесь не проверялось.
(() => {
const faces = Array.from(document.fonts, face => ({
family: face.family,
weight: face.weight,
style: face.style,
stretch: face.stretch,
unicodeRange: face.unicodeRange,
status: face.status
}));
console.table(faces);
console.log("Registered face count:", faces.length);
})();
Используйте этот список, чтобы отличить отсутствие регистрации от зарегистрированного, но неиспользуемого начертания. Если у записи статус error, прежде чем менять типографику, разберитесь со сбоем загрузки. Запись со статусом loaded подтверждает состояние загрузки, однако выбор начертания по-прежнему зависит от элемента и текста. MDN: API загрузки шрифтов CSS
Не считайте document.fonts.check() доказательством отображения. Метод может вернуть true даже для несуществующего семейства. Его необязательный текстовый аргумент сужает подбор по объявленным диапазонам Unicode, но не проверяет покрытие отдельных глифов. Аналогично, document.fonts.ready завершается после загрузки и раскладки используемых шрифтов, но не подтверждает, что было отображено каждое объявленное начертание. MDN: FontFaceSet.check(), MDN: Document.fonts
Покрывает ли шрифт проверяемые символы?
Проверьте и CSS-дескриптор unicode-range, и фактический ресурс шрифта. Дескриптор управляет тем, для каких символов можно использовать начертание. Расширение дескриптора не создаст глифы, которых нет в файле: карта символов шрифта по-прежнему участвует в подборе. MDN: unicode-range, W3C: Подбор начертаний шрифта
Рассмотрим условное правило, ограниченное диапазоном U+0030-0039. В надписи Panel 204 в этот диапазон попадают только 2, 0 и 4. Буквы и пробел не входят в него. Поэтому загрузка, вызванная цифрами, не доказывает, что шрифт способен отобразить всю надпись. По документации MDN, встреча подходящего символа может привести к загрузке всего ресурса шрифта. MDN: unicode-range
Этот самостоятельный пример JavaScript показывает разницу. Он запускается в консоли браузера или Node.js без предварительной настройки. Расчёт диапазона для приведённого примера детерминирован и был выполнен.
const text = "Panel 204";
const rows = Array.from(text, character => {
const value = character.codePointAt(0);
return {
character,
codePoint: "U+" + value.toString(16).toUpperCase().padStart(4, "0"),
inDeclaredRange: value >= 0x30 && value <= 0x39
};
});
console.table(rows);
Если диапазон исключает нужные символы, исправьте неточный дескриптор или предоставьте поднабор, содержащий эти символы. При проверке результата используйте исходный проблемный текст. Не считайте перебор строки тестом формирования текста: для комбинируемых последовательностей нужна обработка кластеров, а стандарт требует учитывать информацию о формировании текста, когда это необходимо. При сравнении результата сохраняйте последовательности целиком. W3C: Подбор шрифта и подбор кластеров
Могло ли шрифту не хватить времени для отображения?
Проверьте font-display, если семейство и покрытие кажутся правильными. У optional крайне короткий период блокировки и отсутствует период подстановки. У fallback короткий период подстановки. Если ресурс приходит после соответствующего временного окна, на этой загрузке страницы может остаться виден резервный текст. swap допускает неограниченный период подстановки после начального периода блокировки. MDN: font-display
Для контролируемой диагностики временно измените затронутое правило на font-display: swap в таблице стилей, передаваемой браузеру, и повторите начальную загрузку в тех же условиях. Если после загрузки теперь появляется нужное начертание, это подтверждает, что причина может быть во времени. Прежде чем оставлять такую настройку, решите, подходит ли странице это визуальное изменение после загрузки. Повторите проверку при первой загрузке и при перезагрузке с кэшем: результат из кэша не воспроизводит исходное время загрузки ресурса.
Что меняется, если текст рисует библиотека или canvas?
Если на странице уже используется Font Face Observer, проверьте наблюдаемое семейство и параметры weight, style и stretch. В документации он описан как загрузчик и средство наблюдения; для него нужны обычные правила @font-face, а если в шрифте нет символов по умолчанию для теста, нужно указать собственную тестовую строку. Время ожидания по умолчанию — три секунды. Тайм-аут наблюдателя и окно font-display браузера — разные условия. Документация Font Face Observer
Из этого следует, что после сообщения наблюдателя об успехе нужно проверить целевой элемент. Наблюдение за доступностью одного начертания не доказывает, что выигравшие CSS-правила элемента запрашивают именно его. Установка ещё одного загрузчика мало поможет, если пока не выяснено, какое начертание отобразилось.
Canvas добавляет отдельный этап рисования. У его контекста рисования есть собственная настройка font; изначально она равна 10px sans-serif, а недопустимое присваивание игнорируется. Поэтому задание семейства CSS для элемента canvas не устанавливает, какой шрифт использует контекст. Проверьте значение, присвоенное контексту рисования, и порядок операций загрузки и рисования. WHATWG: Стили текста canvas
При рисовании текста на canvas дождитесь загрузки зарегистрированного нужного начертания, задайте шрифт контексту, а затем заново нарисуйте затронутую сцену с помощью обычной процедуры рисования приложения. Уже нарисованные пиксели не сменят гарнитуру после загрузки шрифта. Подготовка текста для canvas также использует гипотетическую бесконечно широкую строку, поэтому успешная проверка на canvas не доказывает, что надпись в ограниченном блоке веб-страницы будет переноситься так же. WHATWG: Подготовка текста и его отрисовка
Как подтвердить исправление?
Вернитесь к исходной надписи и повторите наблюдение, которое выявило проблему. Проверьте запрошенные вычисленные значения, отображаемое начертание и нужные символы в исходных условиях загрузки. Для canvas перед сравнением повторно выполните рисование. Сохраните краткую запись элемента, запрошенных свойств, фактически отображённого начертания, ресурса и изменения, которое устранило проблему; так диагностику можно будет воспроизвести.
Завершайте проверку, когда сможете объяснить, почему шрифт не использовался, и показать нужный результат на затронутом тексте. Исправленное объявление семейства, точный поднабор, зарегистрированное начертание, подходящая политика отображения или правильно выполненная повторная отрисовка — каждое решение затрагивает свой этап. Выберите исправление, подтверждённое вашими наблюдениями.
Источники
Справочник по возможностям CSS — Chrome for Developers
Применение других эффектов: включение автоматической тёмной темы, имитация фокуса и многое другое — Chrome for Developers
Ответы DevTools — Что это за шрифт? — Chrome for Developers
Значение атрибута HTML rel="preload" — MDN Web Docs
Свойство CSS font — MDN Web Docs
Правило CSS @font-face — MDN Web Docs
API загрузки шрифтов CSS — MDN Web Docs
FontFaceSet: метод check() — MDN Web Docs
Document: свойство fonts — MDN Web Docs
Дескриптор правила CSS unicode-range — MDN Web Docs
Дескриптор правила CSS font-display — MDN Web Docs
Font Face Observer — Брам Стейн / проект Font Face Observer
Стандарт HTML: элемент canvas — WHATWG