← Назад к вопросам

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

1.8 Middle🔥 141 комментариев
#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Есть ли проблема при загрузке шрифта в течение десяти секунд

Да, это серьёзная проблема для UX и SEO. 10 секунд — это неприемлемо долго. Давайте разберёмся, почему это плохо и как это исправить.

Проблема: Invisible Text Flash (FOIT) и Flash of Unstyled Text (FOUT)

FOIT — Invisible Text Flash

// Пример: шрифт загружается 10 секунд
<link href="https://fonts.googleapis.com/css2?family=Roboto" rel="stylesheet" />

// Что происходит:
// 1-9 секунд: текст НЕВИДИМ (браузер ждет загрузки шрифта)
// 10 секунда: шрифт загружен, текст появляется

// Результат: пользователь видит пустой экран, думает, что сайт сломан

FOUT — Flash of Unstyled Text

/* Альтернатива: показать fallback шрифт, потом заменить */
body {
  font-family: 'MyCustomFont', Arial, sans-serif; /* Falls back to Arial while loading */
}

/* Что происходит: */
/* 1-9 сек: текст видим (Arial) */
/* 10 сек: текст меняется на MyCustomFont */
/* Результат: видимый скачок текста (jerky experience) */

Почему это проблема

1. Плохой UX

Пользователь:
0 сек: нажимает на ссылку, ждет
5 сек: "Что-то не работает?"
10 сек: "Наконец-то!" (текст появляется)

Впечатление: сайт медленный и неотзывчивый

2. Cumulative Layout Shift (CLS)

Это метрика Core Web Vitals, которая влияет на SEO ранжирование Google.

// Когда шрифт меняется с Arial на Roboto, размеры букв меняются
// До загрузки: 16px Arial
// После загрузки: 16px Roboto (другая ширина!)

// Результат: текст прыгает на экране (CLS > 0)
// Google штрафует такие сайты в поиске!

3. High First Input Delay (FID)

Если шрифт загружается, браузер занят, и JavaScript блокируется.

// Пока браузер скачивает шрифт, JavaScript замораживается
// Кликнул на кнопку → ждешь 3 секунды → наконец сработает

// Пользователь: "Кнопка не работает!"

Приемлемые времена загрузки

< 100ms   — Не замечает (идеально)
100-300ms — Замечает небольшое замедление
300-1000ms — Заметно замедление, но терпимо
1-3 сек   — Начинает раздражать
3+ сек    — Плохо, пользователи уходят
10 сек    — Критически плохо!

Решение 1: Preload шрифт (критически важно)

<!-- Скажи браузеру: "Эй, мне нужен этот шрифт, загрузи его в приоритете" -->
<link
  rel="preload"
  href="/fonts/roboto-regular.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

<link
  rel="preload"
  href="/fonts/roboto-bold.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

<!-- Затем используй шрифт -->
<link rel="stylesheet" href="/fonts/styles.css" />

Результат: шрифт начнет загружаться на 1-2 секунды раньше.

Решение 2: Используй font-display: swap

/* В @font-face ОБЯЗАТЕЛЬНО указывай font-display */
@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto.woff2') format('woff2');
  font-display: swap;  /* <-- ОЧЕНЬ ВАЖНО */
}

Значения:

font-display: block   → Ждет 3 сек, потом fallback (FOIT)
font-display: swap    → Сразу fallback, потом заменяет (FOUT)
font-display: fallback → Очень короткое ожидание, потом fallback
font-display: optional → Может вообще не загружать, если слишком медленно

Рекомендация: используй swap

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/my-font.woff2') format('woff2');
  font-display: swap;  /* Показать Arial сразу, потом заменить */
  font-weight: normal;
  font-style: normal;
}

Решение 3: Используй переменный шрифт (Variable Font)

/* Вместо скачивания 4 файлов (normal, bold, italic, bold italic) */
/* Скачай 1 файл, который содержит всё */

@font-face {
  font-family: 'Roboto Flex';
  src: url('/fonts/roboto-flex.woff2') format('woff2-variations');
  font-weight: 100 900;  /* Диапазон весов */
  font-display: swap;
}

Размер файла:

Обычные шрифты:
- roboto-regular.woff2 = 30KB
- roboto-bold.woff2 = 32KB
- roboto-italic.woff2 = 31KB
- roboto-bold-italic.woff2 = 33KB
Итого: 126KB

Переменный шрифт:
- roboto-flex.woff2 = 70KB
Итого: 70KB (экономия 56KB!)

Решение 4: Self-hosted шрифты (вместо Google Fonts)

<!-- ПЛОХО: зависит от google.com -->
<link href="https://fonts.googleapis.com/css2?family=Roboto" rel="stylesheet" />
<!-- DNS lookup: 100ms, загрузка CSS: 200ms, загрузка шрифта: ? -->

<!-- ХОРОШО: со своего сервера -->
<link rel="stylesheet" href="/fonts/roboto.css" />

Файл /public/fonts/roboto.css:

@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto-regular.woff2') format('woff2');
  font-display: swap;
}

@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto-bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

Выигрыш: избегаешь отдельного DNS lookup для google.com, все грузится с одного сервера.

Решение 5: Subset шрифтов (загружай только нужные буквы)

<!-- ПЛОХО: загружаешь все 3000+ символов китайского, а используешь только английский -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP" rel="stylesheet" />
<!-- Размер: 200KB+ -->

<!-- ХОРОШО: загружай только latin буквы -->
<link href="https://fonts.googleapis.com/css2?family=Roboto&subset=latin" rel="stylesheet" />
<!-- Размер: 30KB -->

Инструмент для subsetting:

# Использование pyftsubset (Python tool)
pyftsubset roboto.woff2 --unicodes=U+0020-007E  # Only ASCII

# Или используй tool.glyphrange.com

Решение 6: Async загрузка с timeout

<!-- Загружай шрифт асинхронно, чтобы не блокировать рендер -->
<link
  rel="stylesheet"
  href="/fonts/custom-font.css"
  media="print"
  onload="this.media='all'"
  crossorigin
/>

<!-- Fallback: если загрузка прервется -->
<noscript>
  <link rel="stylesheet" href="/fonts/custom-font.css" />
</noscript>

Решение 7: System fonts (самое быстрое)

/* Используй системные шрифты, ноль задержки */
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', sans-serif;
}

/* Если нужен custom шрифт, загружай его после */
.special {
  font-family: 'MyCustomFont', -apple-system, BlinkMacSystemFont, sans-serif;
}

Полный оптимальный пример (Next.js)

// app/layout.tsx
import { Inter, Roboto } from 'next/font/google';

// Next.js оптимизирует автоматически
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',  // Автоматически добавляет font-display
  preload: true,    // Автоматически preload
});

const roboto = Roboto({
  weight: ['400', '700'],
  subsets: ['latin'],
  display: 'swap',
});

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        {/* Preload критичные шрифты */}
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
      </head>
      <body className={inter.className}>
        {children}
      </body>
    </html>
  );
}

Проверка скорости загрузки шрифтов

# 1. DevTools → Network → фильтр на font
# Смотри сколько времени загружается

# 2. Lighthouse (DevTools → Lighthouse)
# Проверь Core Web Vitals (CLS, LCP, FID)

# 3. PageSpeed Insights
# Раствори https://pagespeed.web.dev

Чеклист оптимизации шрифтов

// ✅ Сделай это:
☑ Используй preload для критичных шрифтов
☑ Добавь font-display: swap
☑ Используй self-hosted шрифты
☑ Subset шрифты (только нужные буквы)
☑ Используй WOFF2 формат
☑ Используй переменные шрифты если возможно
☑ Проверь CLS (Cumulative Layout Shift)
☑ Не загружай больше 2-3 семейств шрифтов

// ❌ Не делай этого:
☒ Не загружай шрифты без preload
☒ Не используй font-display: block
☒ Не загружай ВСЕ варианты (normal, italic, bold, bold-italic)
☒ Не используй Google Fonts без оптимизации
☒ Не блокируй рендер ожиданием шрифта

Пример: реальное время загрузки

БЕЗ оптимизации:
- DNS lookup: 100ms
- Скачивание Google Fonts CSS: 200ms
- Скачивание шрифта: 5000ms
- Рендер с шрифтом: 5300ms

С оптимизацией (preload + swap):
- DNS lookup: 0ms (preconnect)
- Preload шрифта: 500ms (параллельно с CSS)
- Рендер с fallback: 200ms
- Замена на custom шрифт: 500ms (незаметно)
Итого: 500ms (вместо 5300ms!)

Вывод

Загрузка шрифта за 10 секунд — это критическая проблема. Решить её можно:

  1. Preload шрифты — они начнут загружаться раньше
  2. font-display: swap — не ждешь, показываешь fallback
  3. Self-hosted — избегаешь лишних DNS lookups
  4. Subset шрифтов — загружаешь только нужное
  5. System fonts — самый быстрый вариант

Цель: < 100ms загрузка, чтобы пользователь не заметил задержку.

Google штрафует медленные сайты в поиске, так что это важно и для SEO!

Есть ли проблема при загрузке шрифта в течение десяти секунд? | PrepBro