Как работает @font-face в CSS: структура и частые ошибки

@font-face — это CSS-правило, которое связывает имя шрифта с файлами веб-шрифта и позволяет браузеру загрузить их с сервера. Для корректного подключения нужно правильно указать font-family, src и формат файла, а для разных начертаний — отдельные объявления. Ниже разобраны синтаксис, порядок проверки и частые ошибки.
Что такое @font-face и зачем он нужен
Правило @font-face описывает пользовательский шрифт, доступный странице через сеть. Браузер сначала видит имя семейства в CSS, затем по дескриптору src определяет, откуда получить файл. После загрузки шрифт можно использовать в обычном свойстве font-family у body, заголовков, кнопок и других элементов интерфейса.
Это отличается от простого указания системного стека вроде Arial, sans-serif. Системный шрифт уже установлен на устройстве, а веб-шрифт хранится в проекте или на внешнем сервере. Поэтому при подключении важны не только CSS-декларации, но и существование файлов, корректные URL, права доступа и совместимость формата с браузером.
Из чего состоит объявление @font-face
Базовое объявление начинается с конструкции @font-face и блока в фигурных скобках. Внутри указывают имя семейства и источник файла: font-family: BrandSans; src: url('/fonts/brand-sans.woff2') format('woff2');. После этого семейство BrandSans можно назначать элементам через font-family: BrandSans, sans-serif;.
Минимально рабочая запись может содержать font-family и src, однако для реального проекта лучше явно описывать формат и начертание. Это делает таблицу шрифтов предсказуемой: браузер понимает, какой файл использовать для обычного, курсивного, полужирного или переменного варианта.
- font-family задаёт внутреннее имя семейства, под которым шрифт вызывается в остальных правилах CSS.
- src содержит адрес файла и при необходимости его формат; браузер использует источники по порядку.
- format сообщает тип файла, например woff2 или woff, и помогает выбрать подходящий источник.
- font-weight описывает насыщенность: например, 400 для обычного и 700 для полужирного начертания.
- font-style указывает стиль, чаще всего normal или italic.
- font-display определяет поведение текста во время загрузки веб-шрифта.
- unicode-range ограничивает набор символов, который должен обслуживать конкретный файл.
Как правильно подключить WOFF2 и резервный формат
Для большинства современных проектов основным форматом выбирают WOFF2: он предназначен для веб-использования и обычно компактнее старых вариантов. Если требуется дополнительная совместимость с окружениями, где WOFF2 недоступен, в src можно перечислить несколько источников через запятую. Браузер проверяет их последовательно и выбирает подходящий.
Практический вариант выглядит так: @font-face { font-family: SiteText; src: url('/fonts/site-text.woff2') format('woff2'), url('/fonts/site-text.woff') format('woff'); font-weight: 400; font-style: normal; font-display: swap; }. Сначала указан WOFF2, затем WOFF. Порядок важен: более предпочтительный источник ставят первым.
Не следует указывать расширение файла без проверки его реального содержимого. Файл с именем .woff2, переименованный из другого формата, не становится корректным WOFF2. Если сервер отдаёт повреждённый или неподходящий ресурс, браузер пропустит источник, а текст перейдёт на запасной шрифт.
Начертания: font-weight и font-style
Каждое самостоятельное начертание обычно описывают отдельным блоком @font-face. Для обычного начертания используют font-style: normal, для курсива — font-style: italic. Насыщенность задают через font-weight. Если файл содержит начертание 700, браузеру нужно сообщить именно это значение, иначе при запросе font-weight: 700 он может искусственно утолщить обычный файл или выбрать другую доступную запись.
Пример для двух файлов: первый блок связывает SiteText-Regular.woff2 с SiteText, font-weight: 400 и font-style: normal. Второй связывает SiteText-Bold.woff2 с тем же SiteText, font-weight: 700 и font-style: normal. В HTML достаточно назначить заголовку font-family: SiteText, sans-serif; и font-weight: 700; — браузер найдёт нужное объявление по сочетанию параметров.
Если файл является переменным шрифтом, диапазон насыщенности можно задать как font-weight: 200 800. Такой диапазон сообщает браузеру, какие значения поддерживает один файл. Не стоит указывать широкий диапазон для статического файла: это создаёт неверное описание и может привести к неожиданному выбору начертания.
Что делает font-display при загрузке шрифта
Дескриптор font-display управляет тем, как браузер показывает текст до загрузки веб-шрифта. Значение swap обычно позволяет быстро показать текст системным шрифтом, а после загрузки заменить его заданным. Это снижает риск длительного невидимого текста, но может вызвать заметную смену гарнитуры и изменение ширины строк.
Значение block делает акцент на ожидании веб-шрифта: в начале текст может не отображаться, если файл ещё не готов. Значение fallback допускает короткое ожидание и затем использует запасной шрифт. Значение optional позволяет браузеру решить, нужен ли сетевой шрифт в текущих условиях. Выбор зависит от роли гарнитуры: для основного текста часто важнее ранняя читаемость, для фирменного логотипа — точность отображения.
Пути к файлам и расположение ресурсов
URL в src считается относительно таблицы стилей, а не относительно HTML-файла. Если CSS находится в assets/css/main.css, а шрифт — в assets/fonts/text.woff2, путь из CSS может быть ../fonts/text.woff2. Ошибка в одном уровне вложенности приводит к ответу 404, хотя файл физически присутствует в проекте.
Абсолютный путь от корня сайта, например /fonts/text.woff2, удобен при единой структуре публичных ресурсов. Относительный путь без начального слеша зависит от расположения CSS-файла. При сборке проекта также нужно проверить, что файлы шрифтов копируются в итоговую папку и не остаются только в исходной директории.
Кириллица, unicode-range и размер файла
Шрифтовой файл может содержать полный набор символов или только нужные подмножества. Для русскоязычного сайта важно проверить наличие кириллицы, знаков препинания, цифр и специальных символов. Если в файле нет кириллических глифов, браузер возьмёт их из запасного шрифта, поэтому буквы в одной строке могут выглядеть неодинаково.
Дескриптор unicode-range позволяет разделить шрифт на несколько файлов и загружать только наборы символов, которые нужны странице. Например, отдельный ресурс может обслуживать латиницу, а другой — кириллицу. Этот подход требует аккуратной настройки диапазонов: пересечения, пропущенные символы или ошибочные интервалы могут привести к смешению файлов и непредсказуемому результату.
Частые ошибки при подключении веб-шрифтов
Большинство проблем с @font-face связано не с самим CSS-синтаксисом, а с несогласованностью имени, файла и условий загрузки. Проверять нужно не только объявление, но и сетевой запрос в инструментах разработчика браузера. Статус 404 указывает на неверный путь, ошибка CORS — на ограничения доступа, а сообщение о неподдерживаемом формате — на проблему с файлом или его MIME-типом.
- Совпадение имени: в @font-face и в font-family должно использоваться одно и то же имя без случайных пробелов и отличий в написании.
- Правильный путь: URL должен вести к публичному файлу из браузера, а не только к файлу на компьютере разработчика.
- Реальный формат: значение format должно соответствовать содержимому ресурса, а не только его расширению.
- Полный набор начертаний: для 400, 500 и 700 нужны соответствующие файлы или корректно описанный переменный шрифт.
- Доступ с другого домена: внешний сервер должен разрешать загрузку шрифта для домена сайта через CORS.
- Кэш и сборка: после замены файла нужно убедиться, что браузер не использует старую версию из кэша.
- Кириллица: выбранный файл должен содержать символы русского алфавита и необходимые знаки.
Как диагностировать проблему в браузере
Начните с вкладки Network в инструментах разработчика: обновите страницу и отфильтруйте запросы по слову font или расширению файла. Успешный запрос не гарантирует правильное отображение, но отсутствие запроса обычно указывает на ошибку в CSS, невостребованное начертание или блокировку ресурса. Открыв ответ, проверьте статус, размер и тип содержимого.
Затем откройте вкладку Computed или аналогичный раздел и проверьте фактически применённое свойство font-family. Если в списке есть нужное семейство, но визуально используется другая гарнитура, сравните font-weight и font-style элемента с параметрами объявления. Отдельно протестируйте простой текст на латинице и кириллице: так легче обнаружить неполный набор символов.
Чеклист перед публикацией CSS-шрифта
Перед публикацией пройдите проверку от имени пользователя, который открывает сайт в чистом браузере. Важно убедиться, что шрифт не работает только благодаря локальной копии на компьютере разработчика. Проверяйте обычный текст, заголовки, курсив, полужирное начертание, цифры и кириллические символы.
- Проверьте, что каждый URL из src открывается как публичный ресурс и не возвращает ошибку.
- Сопоставьте расширение, format и фактический тип каждого файла.
- Убедитесь, что font-family в объявлении совпадает с именем, используемым в стилях элементов.
- Опишите каждое нужное сочетание font-weight и font-style отдельным объявлением или задайте корректный диапазон переменного шрифта.
- Проверьте наличие кириллицы, цифр, знаков препинания и специальных символов.
- Выберите font-display с учётом приоритета читаемости или точного фирменного отображения.
- Очистите кэш либо измените версию ресурса и повторите проверку после сборки проекта.
FAQ: ответы на вопросы о @font-face
Почему @font-face не работает, хотя файл шрифта есть в папке?
Наличие файла в исходной папке не означает, что он доступен браузеру. Проверьте путь относительно CSS-файла, копирование ресурса в папку сборки, статус сетевого запроса и права доступа. Также сравните имя семейства, font-weight и font-style в объявлении с параметрами элемента, который должен использовать шрифт.
Нужно ли подключать WOFF и WOFF2 одновременно?
Нет, обязательного требования подключать оба формата нет. WOFF2 часто используют как основной веб-формат, а WOFF добавляют как запасной источник для нужных окружений. Если проект обслуживает только современные браузеры и требования совместимости это допускают, одного корректного WOFF2 может быть достаточно.
Почему браузер искусственно делает шрифт жирным?
Обычно браузер не находит отдельное объявление для запрошенного значения font-weight и пытается имитировать насыщенность доступного файла. Например, для элемента с font-weight: 700 может быть подключён только файл с font-weight: 400. Добавьте реальное полужирное начертание или корректно опишите диапазон переменного шрифта.
Как понять, что в файле нет кириллицы?
Сравните отображение латинских и русских букв в одной строке. Если кириллица заметно отличается по рисунку, ширине или высоте, браузер, вероятно, использует запасной шрифт для отсутствующих глифов. Проверить результат можно также в редакторе шрифтов или заменить файл на версию с поддержкой кириллического набора.
Что выбрать: font-display: swap или block?
font-display: swap обычно подходит для основного текста, когда важно показать содержимое без длительного ожидания. block может быть оправдан, если временная замена существенно меняет восприятие фирменного элемента, но при этом пользователь рискует увидеть невидимый текст во время загрузки. Решение нужно принимать с учётом роли шрифта и скорости доставки ресурсов.
Можно ли использовать одно имя для разных файлов шрифта?
Да, одно имя семейства используют для нескольких объявлений, если они описывают разные начертания. Например, SiteText может быть общим font-family для файлов Regular и Bold, а различие задаётся через font-weight. Нельзя бездумно описывать разные по рисунку гарнитуры одним именем: браузер будет считать их вариантами одного семейства.
Почему шрифт работает локально, но не на опубликованном сайте?
На опубликованном сайте меняются пути, домен, правила сервера и результат сборки. Проверьте, попали ли файлы в итоговый пакет, не изменились ли URL из CSS и не блокирует ли сервер загрузку из-за CORS или неверного типа содержимого. Тестируйте именно собранную версию в браузере, а не только исходные файлы.
Вывод
Надёжное подключение @font-face строится на согласованной связке из имени семейства, корректного источника, формата, начертания и правил загрузки. Если шрифт не отображается, сначала проверьте URL и сетевой запрос, затем font-weight, font-style, поддержку кириллицы и ограничения домена. Такой порядок быстро отделяет ошибку CSS от проблемы ресурса.
Если подходящего начертания ещё нет, создайте собственный шрифт для проекта на fontgenerator.ru и подготовьте его к использованию в веб-интерфейсе.