← Назад к вопросам
Как загружаются шрифты если браузер не поддерживает некоторые форматы?
1.0 Junior🔥 191 комментариев
#HTML и CSS
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как загружаются шрифты, если браузер не поддерживает некоторые форматы
Загрузка шрифтов — сложный процесс. Браузер может не поддерживать все форматы, и нужно предусмотреть fallback. Расскажу, как это работает в деталях.
1. Основной механизм — multiple formats
@font-face {
font-family: 'MyFont';
src:
url('/fonts/myfont.woff2') format('woff2'),
url('/fonts/myfont.woff') format('woff'),
url('/fonts/myfont.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
Как это работает:
- Браузер читает список форматов слева направо
- Пытается загрузить первый (
woff2) - Если браузер его поддерживает — загружает и использует
- Если нет — переходит к следующему (
woff) - И так до тех пор, пока не найдёт поддерживаемый или не закончится список
Пример: Internet Explorer не поддерживает woff2
Browser: IE 11
- Пробует woff2? НЕТ (не поддерживает)
- Пробует woff? ДА! Загружает его
- Остальное игнорирует
Browser: Chrome
- Пробует woff2? ДА! Загружает его (самый компактный)
- Остальное игнорирует
2. Форматы шрифтов и поддержка браузерами
| Формат | Размер | IE 9+ | Chrome | Firefox | Safari | Поддержка |
|---|---|---|---|---|---|---|
| WOFF2 | Очень малый | Нет | Да (26+) | Да (39+) | Да (11+) | Отличная для современных |
| WOFF | Малый | Да (6+) | Да | Да | Да (5+) | Универсальная |
| TTF | Средний | Нет | Да | Да | Да | Хорошая |
| OTF | Средний | Нет | Да | Да | Да | Хорошая |
| EOT | Средний | Да (4+) | Нет | Нет | Нет | Только IE (устаревший) |
| SVG | Большой | Нет | Да (?) | Нет | Да | Старые Safari |
3. Лучшая стратегия — минимальный набор
/* Для современных браузеров достаточно WOFF2 + WOFF */
@font-face {
font-family: 'Inter';
src:
url('/fonts/inter.woff2') format('woff2'),
url('/fonts/inter.woff') format('woff');
}
/* Если нужна совместимость со старыми браузерами */
@font-face {
font-family: 'OpenSans';
src:
url('/fonts/opensans.woff2') format('woff2'), /* Chrome 26+, Safari 11+ */
url('/fonts/opensans.woff') format('woff'), /* IE 9+, все современные */
url('/fonts/opensans.ttf') format('truetype'); /* Fallback */
}
4. Система fallback шрифтов (generic families)
Если все форматы не загрузятся, браузер использует систему fallback:
body {
/* Первый выбор — наш шрифт, второй — что-то похожее, третий — generic */
font-family: 'Inter', 'Helvetica Neue', sans-serif;
}
heading {
font-family: 'Playfair Display', 'Georgia', serif;
}
code {
font-family: 'Fira Code', 'Courier New', monospace;
}
Generic families:
sans-serif— без засечек (Helvetica, Arial, Verdana)serif— с засечками (Times New Roman, Georgia)monospace— моноширинный (Courier, Courier New)cursive— рукописный (Comic Sans, Brush Script)fantasy— фантазийный (Impact, Papyrus)
5. Как браузер выбирает шрифт
// Если взять @font-face выше
const computedStyle = window.getComputedStyle(document.body);
console.log(computedStyle.fontFamily);
// Вывод зависит от загрузки:
// 1. Если Inter загрузился: '"Inter"' или просто браузер использует его
// 2. Если не загрузился: '"Helvetica Neue"' (fallback)
// 3. Если ничего не загрузилось: generic sans-serif (системный шрифт)
6. Использование @font-face с media queries
/* Разные шрифты для разных экранов */
@font-face {
font-family: 'MyFont-Light';
src: url('/fonts/myfont-light.woff2') format('woff2');
}
@media (max-width: 768px) {
body {
font-family: 'MyFont-Light', sans-serif; /* Легче для мобильных */
font-size: 14px;
}
}
@media (min-width: 769px) {
body {
font-family: 'MyFont', sans-serif; /* Полный шрифт для десктопа */
font-size: 16px;
}
}
7. Современный подход с Next.js и Google Fonts
// next/font/google автоматически выбирает лучший формат
import { Inter, Playfair_Display } from 'next/font/google';
const inter = Inter({
subsets: ['latin', 'cyrillic'],
display: 'swap' // Показать fallback шрифт пока загружается
});
const playfair = Playfair_Display({
subsets: ['latin'],
weight: ['400', '700'],
variable: '--font-playfair' // CSS переменная
});
export default function App() {
return (
<html className={`${inter.className} ${playfair.variable}`}>
<body>
{/* Inter загружен автоматически */}
<h1 style={{ fontFamily: 'var(--font-playfair)' }}>Title</h1>
</body>
</html>
);
}
Next.js автоматически:
- Выбирает WOFF2 для современных браузеров
- Оптимизирует размер
- Использует
font-display: swapдля быстрой загрузки
8. font-display стратегия
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap; /* Какая стратегия при загрузке? */
}
Варианты:
| Значение | Поведение | Когда использовать |
|---|---|---|
auto | По умолчанию браузера | Редко задаём явно |
block | Ждём 3 сек, потом swap | Для важных шрифтов |
swap | Сразу fallback, потом swap | Для основного текста |
fallback | Сразу fallback, потом swap с таймаутом | Для шрифтов которые не так важны |
optional | Сразу fallback, swap если успели 100мс | Для декоративных шрифтов |
/* Основной шрифт — показываем fallback сразу */
body {
font-family: 'Inter', sans-serif;
}
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap; /* swap для основного текста */
}
/* Декоративный шрифт — можно подождать */
h1 {
font-family: 'Playfair Display', serif;
}
@font-face {
font-family: 'Playfair Display';
src: url('/fonts/playfair.woff2') format('woff2');
font-display: fallback; /* fallback для декоративных */
}
9. Проверка поддержки форматов JavaScript
// Проверяем, что браузер поддерживает
const isFontFormatSupported = async (format) => {
try {
return await document.fonts.check(`1em TestFont`);
} catch {
return false;
}
};
// Более правильная проверка
function isFontSupported(fontName) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const text = 'Test';
const width1 = ctx.measureText(text).width;
ctx.font = `12px "${fontName}", sans-serif`;
const width2 = ctx.measureText(text).width;
return width1 !== width2; // Если отличается — шрифт загружен
}
console.log(isFontSupported('Inter')); // true/false
10. Практический пример: полная стратегия
/* HTML файл */
<head>
<style>
/* 1. Локальный системный шрифт (максимально быстро) */
@font-face {
font-family: 'Inter';
src: local('Inter');
}
/* 2. Скачиваемые форматы (для современных браузеров) */
@font-face {
font-family: 'Inter';
src:
url('/fonts/inter.woff2') format('woff2'),
url('/fonts/inter.woff') format('woff');
font-display: swap;
}
</style>
</head>
<body style="font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;">
<!-- Если Inter не загрузился, будет использован fallback -->
</body>
11. Оптимизация размера
# Уменьшаем размер шрифта, используя subsetting
# Берём только нужные символы (например, только латинский + кириллица)
# Инструмент: subsetter (например, FontTools)
fonttools subset myfont.woff2 --unicodes="U+0000-007F,U+0400-04FF"
output myfont-subset.woff2
Ключевой вывод
Браузер загружает шрифты следующим образом:
- Читает @font-face слева направо по форматам
- Пытается загрузить первый поддерживаемый формат
- Если не поддерживается — переходит к следующему
- Если ничего не загрузилось — использует fallback шрифт
- Если fallback тоже нет — использует generic family (sans-serif, serif, etc.)
Рекомендации:
- Используй WOFF2 + WOFF для современных браузеров
- Добавь TTF для совместимости
- Используй font-display: swap для быстрой загрузки
- Всегда указывай fallback:
font-family: 'MyFont', sans-serif - Для Next.js используй next/font (это автоматизирует всё)