Браузер встречает <link rel="preload"> в HTML ещё до того, как начнет распарсивать CSS-файлы. Это фундаментальное отличие от того, как обычно загружаются шрифты. Стандартный поток выглядит медленно и последовательно: браузер читает HTML → находит упоминание CSS → скачивает CSS → видит @font-face → запрашивает файл шрифта с сервера. На быстрых сетях это несколько десятков миллисекунд, но на мобилке с 3G каждый этап добавляет задержку. С preload вы перехватываете эту цепочку: браузер начнет загружать файл шрифта сразу со своим высоким приоритетом, параллельно со всеми остальными ресурсами, ещё до того как он понадобится для отображения текста.
Синтаксис link rel="preload" и разбор каждого атрибута
Вот как выглядит правильное подключение шрифтов с preload:
<link rel="preload" href="fonts/roboto.woff2" as="font" type="font/woff2" crossorigin>
rel="preload" — этим атрибутом вы говорите браузеру, что это критический ресурс, который нужно загрузить заранее. Без preload браузер обнаруживает шрифты, только когда парсит CSS и находит там @font-face. С preload загрузка шрифта начинается в момент, когда парсер заметил саму ссылку в HTML.
href="fonts/roboto.woff2" — путь к файлу шрифта на вашем сервере или CDN. Обычно используется формат woff2, потому что он компактнее других форматов для веба и имеет полную поддержку современными браузерами в 2026 году.
as="font" — это критически важный атрибут. Браузер должен знать, что он загружает именно шрифт, а не скрипт, стиль или изображение. Без этого браузер может неправильно расставить приоритеты загрузок и начнет загружать другие ресурсы раньше, чем файл шрифта, что замедлит первое отображение текста на странице.
type="font/woff2" — формат файла шрифта. Браузер проверит поддержку этого формата и проигнорирует тег, если его версия не поддерживает woff2. Это безопасно: старые браузеры просто не загрузят файл по этому тегу, а будут использовать обычный способ через CSS и @font-face.
crossorigin — атрибут для загрузки файла с другого домена. Если шрифты хранятся на CDN или в Google Fonts, браузеру нужны правильные заголовки CORS, чтобы разрешить загрузку и кэширование. Без crossorigin файл может загрузиться, но кэширование может работать неправильно, и вы потеряете часть преимуществ от preload.
Как браузер парсит и загружает preload-тег
При разборе HTML браузер встречает <link rel="preload"> и выполняет несколько этапов обработки.
Сначала браузер просто обнаруживает наличие ресурса и его характеристики. На этом же этапе, если это возможно, решает, нужна ли загрузка. Браузер смотрит на type и as атрибуты, проверяет, есть ли в них что-то, что браузер не поддерживает. Если всё согласовано, добавляет в очередь загрузок.
Затем браузер назначает высокий приоритет этому ресурсу. У браузера есть внутренняя система приоритизации: критические ресурсы получают HIGH, остальные — MEDIUM и LOW. Шрифты, указанные через preload с as="font", получают HIGH приоритет, наравне с основным CSS и HTML. Картинки, трекеры, дополнительные скрипты — LOW.
После этого браузер начинает загружать файл шрифта параллельно со всеми остальными ресурсами. Это не препятствует загрузке других файлов, просто конкурирует за пропускную способность с высоким приоритетом.
Наконец, когда файл приходит в браузер, он кэшируется. Когда парсер CSS встречает @font-face с тем же путём к файлу, браузер не запрашивает файл заново — просто берёт его из памяти. Это моментально.
Весь этот процесс сокращает время с момента начала загрузки страницы до момента, когда текст появляется на экране в правильном шрифте. Это называется улучшением LCP (Largest Contentful Paint) и измеряется в миллисекундах.
FOIT и FOUT: поведение браузера при загрузке шрифта
Пока файл шрифта загружается, браузер не может сразу отобразить текст нужным шрифтом. Разные браузеры решают эту дилемму по-разному, и возникают два явления: FOIT и FOUT.
FOIT (Flash of Invisible Text) — браузер скрывает текст. Вместо букв пользователь видит пустое белое пространство несколько секунд, пока скачивается файл. Сайт выглядит сломанным. Это было поведением по умолчанию в старых браузерах и создавало плохое впечатление.
FOUT (Flash of Unstyled Text) — браузер показывает текст системным шрифтом (обычно Arial или Georgia), а потом, как только загружается нужный шрифт, текст переоформляется. Пользователь видит мерцание, когда текст меняет свой вид. Это менее плохо, чем FOIT, но всё равно заметно.
Решение — использование font-display: swap в правиле @font-face:
@font-face {
font-family: 'Roboto';
src: url('/fonts/roboto.woff2') format('woff2');
font-display: swap;
}
Значение swap говорит браузеру: сразу показывать текст в fallback-шрифте, а когда загрузится правильный шрифт, заменить его. Это означает, что пользователь видит контент немедленно, пусть и не в идеальном стиле.
Комбинация preload и font-display: swap работает синергетически. Браузер начинает загружать файл шрифта раньше благодаря preload, системный шрифт отображает текст немедленно благодаря swap. К моменту, когда нужный шрифт загружается, задержка настолько мала, что переход почти незаметен. LCP улучшается значительно, а CLS (Cumulative Layout Shift) остаётся минимальным.
Пример с Google Fonts
Google Fonts — самый популярный способ подключения шрифтов на веб-сайтах, но он не использует preload. Раньше выглядело просто:
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700" rel="stylesheet">
Браузер находит этот тег, запрашивает CSS у Гугла, получает файл с описанием @font-face, потом запрашивает сами файлы шрифтов. Минимум две сетевые операции, две задержки.
Оптимизированный способ выглядит так:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="preload" href="https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Me5WZLCzYlKXg.woff2" as="font" type="font/woff2" crossorigin>
Вот что тут происходит по порядку:
Два тега rel="preconnect" устанавливают соединение заранее. Браузер делает DNS lookup и устанавливает SSL-соединение до того, как потребуется загружать данные. Это сберегает время на первые запросы.
Затем идёт обычная ссылка на CSS с параметром display=swap, который говорит сервису Google Fonts вернуть CSS с font-display: swap в @font-face правилах.
Наконец, rel="preload" загружает конкретный файл woff2 прямо параллельно, не дожидаясь, пока браузер распарсит CSS.
Результат: вместо последовательной цепочки (HTML → ожидание → CSS → ожидание → шрифты) вы получаете параллельную загрузку. Все ресурсы скачиваются одновременно. Эффект на LCP зависит от шрифта, сети и других ресурсов страницы.
Браузерная поддержка rel="preload"
На 2026 год rel="preload" поддерживают практически все современные браузеры:
Chrome с версии 50 и выше имеет полную поддержку. Firefox с версии 85 поддерживает preload корректно. Safari поддерживает с версии 11.1. Edge, основанный на Chromium, поддерживал всегда.
В старых браузерах (IE9, древние версии мобильных браузеров) теги rel="preload" просто игнорируются. Это не создаёт ошибок — шрифты будут загружаться стандартным способом, медленнее, но сайт продолжит работать.
Использование preload абсолютно безопасно с точки зрения совместимости. Вы не сломаете ничего, если добавите эти теги — в худшем случае они просто не будут применяться.
Для опытных разработчиков: приоритеты и конкуренция за пропускную способность
На уровне Senior-разработчика важно понимать, как preload вписывается в распределение приоритетов загрузок и как избежать того, чтобы preload замедлил загрузку других критических ресурсов.
Браузер имеет лимит на количество одновременных соединений — обычно 6 на одном домене. Если вы используете preload для десяти шрифтов, текстур и других ресурсов, они будут конкурировать за эти 6 слотов. Медленные соединения почувствуют это особенно остро.
Правильная стратегия: используйте preload для 1–3 самых критических шрифтов. Это основной roman шрифт, может быть bold вариант, может быть italic. Остальные шрифты подключайте через обычный CSS без preload. Это даёт максимальный выигрыш без конкуренции за пропускную способность.
Помимо этого, следите за тем, чтобы preload не конкурировал с другими критическими ресурсами. Если у вас есть критический JS или CSS, загружаемые также с высоким приоритетом, они могут блокировать друг друга на медленных сетях.
Ещё один совет: если вы используете несколько вариантов одного шрифта (Roboto 400, Roboto 700, Roboto italic), убедитесь, что в preload вы указываете именно те файлы, которые используются на экране. Загружать шрифты, которые потом не используются, — пустая трата пропускной способности.
Проверьте влияние preload на LCP в полевых и лабораторных замерах. Результат зависит от страницы и требует проверки замерами.
