Fluid-типографика: полное руководство по созданию адаптивных и доступных текстов
Адаптивный веб-дизайн — это искусство создания сайтов, которые одинаково хорошо работают на любом устройстве, в любом браузере и с любыми пользовательскими настройками. Когда дело доходит до типографики, мы обычно думаем: "нужно менять размер шрифта в зависимости от ширины экрана". И это правильно. Но есть нюанс.
Проблема в том, что за красивой адаптивностью легко потерять человека.
Представьте: пользователь специально установил в браузере крупный шрифт, потому что иначе ему трудно читать. А ваш "умный" адаптивный дизайн это проигнорировал. Или наоборот — текст красиво растёт на широком мониторе, но когда человек пытается увеличить страницу (Ctrl++ / Cmd++), ничего не происходит.
В этой статье мы не просто сделаем текст красивым. Мы создадим систему, которая:
- Плавно подстраивается под любой экран
- Уважает личные настройки каждого пользователя
- Проходит проверку на доступность (WCAG)
- И при этом требует минимум кода и максимум здравого смысла
Поехали!
Фундамент: уважение к пользователю
Прежде чем писать хоть строчку CSS, давайте договоримся о главном принципе:
Пользователь всегда знает лучше.
Звучит пафосно? Давайте на примерах.
Два главных инструмента пользователя
Каждый, кто заходит на ваш сайт, имеет два простых способа повлиять на размер текста:
Настройки браузера. Можно раз и навсегда установить комфортный базовый размер шрифта. Где-то это 16 пикселей (стандарт), где-то 20, а где-то 14 — зависит от зрения, монитора и личных предпочтений.
Масштабирование (Ctrl++ / Cmd++). Временное увеличение или уменьшение всего сразу. Удобно, когда нужно быстро разглядеть мелкий текст или, наоборот, увидеть больше информации на экране.
Золотое правило (запомните его)
Ваш CSS не должен отнимать у пользователя эти возможности.
Звучит очевидно? Тогда смотрите, как легко это нарушить:
/* ❌ Плохо: жёстко задаём размер в пикселях */
html {
font-size: 16px; /* Настройки пользователя? Не, не слышали */
}
/* ❌ Ещё хуже: привязываемся только к ширине экрана */
html {
font-size: 2vw; /* Красиво? Да. Доступно? Нет. */
}В обоих случаях мы говорим пользователю: "Твои предпочтения не важны, я сам решу, каким тебе читать".
Компромисс, который работает
Наша задача — найти баланс. Мы хотим, чтобы текст:
- Подстраивался под экран (это красиво и удобно на разных устройствах)
- Но при этом слушался пользователя (это доступно и человечно)
Весь дальнейший код в этой статье будет построен вокруг одной простой идеи:
Начинаем с пользовательских настроек (1em). Добавляем адаптивность (vw). Ограничиваем крайности (clamp()).
И никогда не наоборот.
Три способа договориться с пользователем о базовом размере
Итак, мы договорились: начинаем с уважения к пользователю. Но как это реализовать в коде? Есть три подхода. Первый — простой, но с подвохом. Второй — умный компромисс. Третий — идеальный баланс.
Способ 1. Простой (но грубый): относительная подгонка
Самый очевидный способ — использовать относительные единицы. Если стандартный размер в браузере — 16px, а нам для дизайна нужно 20px, просто умножаем:
html {
/* 20px как цель, 16px как ожидание: 20/16 = 1.25 */
font-size: 1.25em;
}Или более явно, через calc():
html {
font-size: calc(20 / 16 * 1em);
}В чем подвох?
Этот подход вроде бы учитывает пользователя (мы используем em), но на самом деле он просто умножает его настройки. Если пользователь специально поставил 20px, то после наших манипуляций получится 25px. А если у него 24px — будет 30px.
Способ 2. Умный: пусть clamp() решает
А что, если сказать браузеру так: «Вот идеальный размер по мнению дизайнера — 20px. Но если пользователь хочет крупнее — уступи ему. Если хочет намного мельче — не дай тексту стать нечитаемым»?
Это делает функция clamp():
html {
font-size: clamp(
1em, /* Минимум: что хочет пользователь (ниже нельзя) */
20px, /* Идеал: что хотим мы */
1.25em /* Максимум: +25% от желаний пользователя (выше нельзя) */
);
}Как это работает (очень важный момент):
Браузер смотрит на три значения и выбирает среднее:
- Если
20pxменьше, чем пользовательский1em— берётся1em(пользователь важнее) - Если
20pxбольше, чем1.25em— берётся1.25em(мы не даём тексту распухнуть) - Во всех остальных случаях — берётся
20px(дизайн работает)
✅ Плюс: Мы не умножаем вслепую, а договариваемся в разумных пределах.
⚠️ Минус: Мы все ещё мыслим в пикселях, а пиксели — зло для доступности.
Способ 3. Идеальный: полный отказ от пикселей
Пиксели обманчивы. Они создают иллюзию контроля, но на самом деле:
- Не реагируют на пользовательские настройки шрифта
- По-разному выглядят на разных экранах
- Ломаются при масштабировании
Идеальная формула использует только относительные единицы:
html {
font-size: clamp(
1em, /* Минимум = настройки пользователя */
1em, /* Предпочтение = тоже настройки (но мы их позже скорректируем) */
1.5em /* Максимум = +50% (но в рамках WCAG) */
);
}"Но погодите, — скажете вы, — здесь же предпочтение равно минимуму! Зачем тогда вообще clamp?"
Отличный вопрос. Сейчас это действительно выглядит бессмысленно. Но в следующем разделе мы добавим сюда адаптивность, и формула оживёт. А пока запомните главное:
Любая формула базового размера должна начинаться с 1em и использовать clamp() для контроля границ. Пикселям здесь не место.
Добавляем адаптивность: от скачков к плавности
Теперь, когда мы научились договариваться с пользователем о базовом размере, пора добавить адаптивность. Текст должен понимать: на телефоне места мало — будь поменьше, на широком мониторе — можно и разрастись.
Есть два принципиально разных подхода. Один — старый, надёжный, но с недостатками. Второй — современный и гибкий.
Подход А. Классический (ступенчатый): медиазапросы
То, чему нас учили последние 10 лет: ставим точки прерывания и переключаем размеры.
html {
font-size: 1em; /* База */
}
@media (width > 30em) {
html { font-size: 1.125em; } /* 18px если база 16px */
}
@media (width > 45em) {
html { font-size: 1.25em; } /* 20px если база 16px */
}Когда это хорошо:
- Когда дизайн жёстко привязан к конкретным устройствам
- Когда важна предсказуемость (например, для печати)
- В проектах с консервативными требованиями
Когда это плохо:
- Текст "скачет" при изменении размера окна
- Нужно просчитывать и поддерживать кучу точек прерывания
- Между точками прерывания размер не оптимален
Подход Б. Современный (плавный): viewport units
А что, если размер будет меняться непрерывно, плавно следуя за шириной экрана?
Для этого есть vw (viewport width) — 1% от ширины окна браузера.
/* Опасно! Чистые vw ломают доступность */
html {
font-size: 2vw; /* НЕ ДЕЛАЙТЕ ТАК */
}Почему опасно? Потому что при масштабировании (Ctrl++) ничего не произойдёт — текст останется привязан к ширине окна, а не к желанию пользователя увеличить шрифт.
Идеальный гибрид: clamp() + vw + em
А теперь магия. Соединяем три идеи:
- Уважение к пользователю:
1emкак нижняя граница - Адаптивность:
vwдля плавного роста - Контроль:
clamp()чтобы не переборщить
html {
font-size: clamp(
1em, /* Нижняя граница: настройки пользователя */
0.5em + 0.5vw, /* Плавный рост: гибрид */
1.25em /* Верхняя граница: не больше +25% */
);
}Как это работает:
- На телефоне (узкий экран):
vwмаленький, работает нижняя граница1em - На десктопе (широкий экран):
vwдобавляет вес, размер растёт - Если пользователь увеличил базовый шрифт: все пропорции сохраняются
- При масштабировании: работает, потому что
em-часть реагирует
Готовая формула для копирования
Базовый шаблон, который можно использовать в любом проекте:
:root {
/* Настраиваемые параметры */
--min-font: 1em; /* Минимум = настройки пользователя */
--max-font: 1.25em; /* Максимум = +25% */
--viewport-influence: 0.5vw; /* Сила влияния ширины экрана */
/* Готовое решение */
font-size: clamp(
var(--min-font),
calc(1em + var(--viewport-influence)),
var(--max-font)
);
}Как подобрать параметры:
- Для новостных сайтов, блогов:
--max-fontможно увеличить до1.5em - Для интерфейсов, дашбордов: держите
--max-fontв районе1.125em --viewport-influence:начинайте с0.3vwи тестируйте на разных экранах
Скрытая угроза: почему красивая плавность может сломать доступность
У нас есть отличная формула. Текст плавно растёт на широких экранах, сужается на мобильных, учитывает настройки пользователя. Красота!
Но есть одна деталь, о которой забывают 99% разработчиков. И эта деталь может сделать ваш сайт недоступным для людей с нарушением зрения.
Два разных действия, которые CSS не различает
Давайте проведём эксперимент. Откройте любой сайт и сделайте два простых действия:
- Измените ширину окна браузера (растяните или сузьте)
- Измените масштаб (Ctrl + / Cmd +)
Вопрос: чем эти действия отличаются с точки зрения пользователя?
Ответ: Всем. Первое — управление пространством, второе — управление читаемостью.
А теперь вопрос к CSS: чем они отличаются с точки зрения браузера?
Ответ: Ничем. И там, и там меняется количество пикселей в окне.
Это ключевое противоречие. Когда пользователь масштабирует страницу, браузер думает, что изменился размер окна. И если ваш текст жёстко привязан к ширине окна, масштабирование... не сработает!
Как это выглядит на практике
Представим два сценария:
Сценарий А (плохой):
html {
font-size: 2vw; /* Только vw, без защиты */
}На широком мониторе текст крупный. Но если пользователь с плохим зрением попытается увеличить страницу до 200% — ничего не произойдёт. Текст останется того же размера, потому что его размер зависит только от ширины окна, а не от масштаба.
Сценарий Б (хороший):
html {
font-size: clamp(1em, 1em + 0.5vw, 1.25em);
}При масштабировании em-часть сработает, и текст увеличится. Пропорции сохранятся, читаемость — тоже.
Главный риск: провал WCAG
Стандарт доступности WCAG имеет чёткое требование (1.4.4): пользователь должен иметь возможность увеличить текст до 200% без потери функциональности.
Если ваш текст слишком сильно зависит от ширины экрана, это требование может быть нарушено. Особенно на широких мониторах.
[!] Правило доступности WCAG 1.4.4
Чтобы текст гарантированно масштабировался до 200%:
Максимальный размер <= Минимальный размер × 2.5Почему именно 2.5? Потому что даже при максимальном масштабировании в браузере (обычно 500%) у вас должен оставаться запас для выполнения требования 200%.
Проверьте себя
/* ❌ Нарушение: максимум слишком далёк от минимума */
html {
font-size: clamp(1em, 1em + 1vw, 3em); /* 3 > 1 × 2.5 */
}
/* ⚠️ На грани: лучше уменьшить максимум */
html {
font-size: clamp(1em, 1em + 0.5vw, 2.4em); /* 2.4 < 2.5 - ОК, но рискованно */
}
/* ✅ Безопасно: запас прочности есть */
html {
font-size: clamp(1em, 1em + 0.3vw, 1.8em); /* 1.8 < 2.5 - комфортно */
}Чек-лист для самопроверки
Перед тем как запустить проект, сделайте простые тесты:
- Установите в браузере крупный шрифт (например, 20px вместо 16). Ваши относительные размеры должны адекватно отреагировать.
- Увеличьте масштаб до 200%. Текст должен стать крупнее, интерфейс не должен сломаться.
- Проверьте на самом широком экране. При масштабировании 200% текст должен увеличиваться, а не оставаться прежним.
Главный вывод
Плавность — это красиво. Доступность — это обязательно.
Любое использование vw должно быть сбалансировано em и ограничено clamp() с соблюдением правила 2.5×.
Собираем всё вместе: идеальная формула
Мы прошли долгий путь. Давайте вспомним, какие требования мы предъявляли к идеальной типографике:
| Требование | Как выполняем |
|---|---|
| Уважение к пользователю | Используем 1em как базовую единицу |
| Адаптивность к экрану | Добавляем vw для плавного роста |
| Контроль крайностей | Применяем clamp() с разумными границами |
| Доступность (WCAG) | Следим, чтобы max ≤ min × 2.5 |
| Масштабируемость | em-часть реагирует на увеличение |
Итоговая формула
Вот она — формула, которая удовлетворяет всем требованиям:
:root {
/* Настраиваемые параметры */
--min-scale: 1em; /* Минимум = настройки пользователя */
--max-scale: 1.25em; /* Максимум = +25% (запас до 2.5×) */
--viewport-influence: 0.5vw; /* Сила влияния ширины экрана */
/* Итоговое правило */
font-size: clamp(
var(--min-scale),
calc(1em + var(--viewport-influence)),
var(--max-scale)
);
}Как это работает (разбор формулы)
Давайте разберём по косточкам, что здесь происходит:
--min-scale: 1em
Нижняя граница. При любых раскладах текст не станет мельче, чем хочет пользователь. Даже на самом узком экране.
--max-scale: 1.25em
Верхняя граница. Текст не вырастет больше чем на 25% относительно пользовательских настроек. Это даёт запас для масштабирования: 1.25 × 2 = 2.5 — ровно граница WCAG.
--viewport-influence: 0.5vw
Скорость роста. На узком экране (320px) добавит 0.5 × 3.2 = 1.6px к базе. На широком (1920px) — 0.5 × 19.2 = 9.6px. Плавно и предсказуемо.
calc(1em + var(--viewport-influence))
Гибридное значение, которое браузер будет пытаться использовать. Оно одновременно:
- Реагирует на масштабирование (через
1em) - Реагирует на ширину экрана (через
vw)
clamp()
Следит, чтобы мы не вышли за разумные пределы, что бы ни случилось с экраном.
Как настроить под свой дизайн
Теперь самое главное — как подобрать параметры для конкретного проекта.
Шаг 1. Определите минимальный и максимальный размеры
Спросите себя: насколько крупным должен быть текст в самых крайних ситуациях?
| Тип контента | Рекомендуемый --max-scale | Пояснение |
|---|---|---|
| Блоги, статьи, новости | 1.5em | Текст должен хорошо читаться на любом экране |
| Интерфейсы, дашборды | 1.125em — 1.25em | Важнее вместить больше информации |
| Детские сайты | 1.75em | Крупный текст для начинающих читателей |
| Сайты для пожилых | 2em (но осторожно с WCAG!) | Максимальная читаемость |
Шаг 2. Настройте скорость роста
--viewport-influence определяет, как быстро текст будет расти с расширением экрана.
0.3vw— очень медленный рост, почти незаметный0.5vw— умеренный рост, хорош для большинства проектов0.8vw— быстрый рост, текст заметно крупнее на широких экранах1vw— агрессивный рост, используйте только с очень низким --max-scale
Шаг 3. Проверьте на реальных устройствах
Никакая теория не заменит живого тестирования. Откройте сайт на телефоне, планшете, ноутбуке и большом мониторе. Увеличьте масштаб до 200%. Убедитесь, что всё читаемо.
Примеры для разных сценариев
Сайт-визитка (консервативный подход):
:root {
--max-scale: 1.125em;
--viewport-influence: 0.3vw;
}Блог (сбалансированный подход):
:root {
--max-scale: 1.4em;
--viewport-influence: 0.6vw;
}Лендинг (акцент на читаемость):
:root {
--max-scale: 1.6em;
--viewport-influence: 0.5vw;
}Что дальше
С базовым размером разобрались. Теперь нужно выстроить гармоничную систему для всех элементов — заголовков, подзаголовков, мелкого текста. Об этом — в следующем разделе.
Строим систему: типографическая шкала с помощью pow()
Базовый размер мы настроили. Теперь нужно создать гармоничную систему для всех текстовых элементов: заголовков, подзаголовков, подписей, мелкого текста.
Раньше мы делали это "на глаз":
h1 { font-size: 32px; }
h2 { font-size: 24px; }
h3 { font-size: 20px; }
p { font-size: 16px; }
small { font-size: 14px; }Это работает, но у такого подхода три проблемы:
- Нет системы — размеры выбраны случайно, нет математической гармонии
- Адаптивность придётся настраивать для каждого элемента отдельно
- При изменении базового размера всё ломается
Музыка и математика в типографике
В музыке есть понятие "интервал" — соотношение между нотами. В типографике работает та же логика: гармоничные соотношения размеров создают ощущение порядка и красоты.
Вот классические музыкальные интервалы, которые отлично работают в типографике:
:root {
/* Музыкальные пропорции */
--minor-second: 1.067; /* малая секунда - едва заметно */
--major-second: 1.125; /* большая секунда - очень осторожно */
--minor-third: 1.2; /* малая терция - хороша для контраста */
--major-third: 1.25; /* большая терция - заметный контраст */
--perfect-fourth: 1.333; /* чистая кварта - сильный контраст */
--perfect-fifth: 1.5; /* чистая квинта - очень сильный */
/* Золотое сечение */
--golden-ratio: 1.618; /* для смелых дизайнов */
}Но просто взять и умножать базовый размер на эти коэффициенты — не лучшая идея. Нужно, чтобы система была:
- Гибкой — легко менять общую пропорцию
- Адаптивной — пропорции могут меняться на разных экранах
- Прозрачной — код должен быть понятным
Знакомьтесь: pow()
Современный CSS умеет делать то, что раньше требовало препроцессоров — математические вычисления. Функция pow() возводит число в степень.
/* Это магия, но простая */
--large: calc(1rem * pow(1.2, 1)); /* 1.2 × 1.2¹ = 1.44rem */
--x-large: calc(1rem * pow(1.2, 2)); /* 1.2 × 1.2² = 1.728rem */
--xx-large: calc(1rem * pow(1.2, 3)); /* 1.2 × 1.2³ = 2.074rem */Создаём готовую систему
Вот полная система, которую можно скопировать и использовать:
:root {
/* Базовый размер (из предыдущего раздела) */
--min-scale: 1em;
--max-scale: 1.25em;
--viewport-influence: 0.5vw;
font-size: clamp(
var(--min-scale),
calc(1em + var(--viewport-influence)),
var(--max-scale)
);
/* === ТИПОГРАФИЧЕСКАЯ ШКАЛА === */
/* Выберите одну пропорцию или меняйте под экран */
--scale-ratio: 1.2; /* малая терция - универсальный выбор */
/* Мелкие размеры (дробные степени) */
--text-xs: calc(1rem * pow(var(--scale-ratio), -0.5)); /* мельче базового */
--text-sm: calc(1rem * pow(var(--scale-ratio), -0.25)); /* чуть мельче */
/* Базовый */
--text-base: 1rem;
/* Крупные размеры (целые степени) */
--text-lg: calc(1rem * pow(var(--scale-ratio), 1));
--text-xl: calc(1rem * pow(var(--scale-ratio), 2));
--text-2xl: calc(1rem * pow(var(--scale-ratio), 3));
--text-3xl: calc(1rem * pow(var(--scale-ratio), 4));
--text-4xl: calc(1rem * pow(var(--scale-ratio), 5));
/* Адаптивная шкала: на широких экранах пропорция меняется */
@media (width > 60em) {
--scale-ratio: 1.333; /* чистая кварта - больше контраста */
}
}
/* Использование в проекте */
h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }
p, li { font-size: var(--text-base); }
figcaption { font-size: var(--text-sm); }
.legal-note { font-size: var(--text-xs); }Почему это гениально
- Меняете одну цифру —
--scale-ratio— и перестраивается вся система - Адаптивность автоматическая — все размеры наследуют поведение базового
- Математическая гармония — соотношения между элементами всегда идеальны
- Понятные имена —
text-sm,text-lgвместо магических чисел
Примеры для разных стилей
Консервативный сайт (едва заметные различия):
:root {
--scale-ratio: 1.125; /* большая секунда */
}
/* h1 будет всего в 1.6 раза крупнее текста */Современный блог (хороший контраст):
:root {
--scale-ratio: 1.25; /* большая терция */
}
/* h1 будет в 3 раза крупнее текста */Креативный проект (сильный контраст):
:root {
--scale-ratio: 1.5; /* чистая квинта */
}
/* h1 будет почти в 8 раз крупнее текста */Важное предупреждение
Помните про доступность! Даже для заголовков действует то же правило: при масштабировании 200% текст должен быть читаем. Если ваш --scale-ratio слишком велик, заголовки могут вылезти за пределы экрана при увеличении.
Золотое правило: проверяйте самый крупный заголовок при масштабе 200% на самом узком экране.
Контейнерные запросы и будущее
Мы построили мощную систему. Текст уважает пользователя, плавно подстраивается под экран, доступен для всех и математически гармоничен. Но веб-разработка не стоит на месте.
Ограничение текущего подхода
Всё, что мы делали до сих пор, основано на одном допущении: экран — главный контекст. Мы смотрим на ширину окна браузера и подстраиваем текст.
Но в современном вебе это не всегда так. Представьте:
- Сайдбар — узкая колонка, где даже крупный заголовок должен быть скромным
- Карточка товара — может быть и маленькой в каталоге, и большой на отдельной странице
- Статья с комментариями — основной текст широкий, комментарии узкие
Размер элемента теперь зависит не только от экрана, но и от родительского контейнера.
Контейнерные запросы — новый мощный инструмент
CSS научился смотреть не только на окно браузера, но и на конкретный контейнер:
/* Говорим: этот элемент важен для контейнерных запросов */
.card-container {
container-type: inline-size;
}
/* Теперь можно делать запросы к контейнеру, а не к экрану */
@container (width > 40em) {
.card-title {
font-size: var(--text-xl);
}
}
@container (width < 20em) {
.card-title {
font-size: var(--text-base);
}
}Контейнерные единицы
Вместе с запросами пришли и новые единицы измерения:
cqw—1%от ширины контейнераcqh—1%от высоты контейнераcqi—1%от размера контейнера по встроенной оси (обычно ширина)cqb—1%от размера по блочной оси (обычно высота)
Теперь наша формула может учитывать не только экран, но и родительский элемент:
.card {
font-size: clamp(
0.9em,
0.8em + 2cqi,
1.2em
);
}Что это меняет
С контейнерными запросами один и тот же компонент может выглядеть по-разному в разных контекстах — и это будет происходить автоматически, без лишних медиазапросов.
Будущее типографики: один раз написанный компонент сам понимает, где он находится, и подбирает оптимальный размер.
Что изучать дальше
Чувствуете, что хотите копнуть ещё глубже? Освоив fluid-типографику, вы открываете дверь в мир современного CSS. Вот следующие ступени для профессионального роста:
- Контейнерные запросы — основа современной компонентной архитектуры
- CSS-функции —
min(),max(),clamp(),pow(),sqrt()и другие - Логические свойства —
margin-inline,padding-blockвместо привязки к физическим направлениям - CSS-каскадные слои — для управления сложными проектами
Главное, что нужно запомнить
Технологии меняются, но принципы остаются:
- Уважение к пользователю всегда в приоритете
- Адаптивность — это про контекст, а не про экраны
- Доступность — не опция, а обязательное требование
- Гармония достигается системой, а не подбором чисел
Заключение: главные принципы (краткий чек-лист)
Мы проделали огромный путь. От простого "сделать текст адаптивным" до сложной, но элегантной системы, которая учитывает всё: желания пользователя, размер экрана, требования доступности и математическую гармонию.
Давайте соберём всё, что мы узнали, в один короткий чек-лист. Сохраните его, повесьте над рабочим столом, возвращайтесь к нему в каждом проекте.
Чек-лист идеальной типографики
Всегда начинайте с
1emЭто не просто единица измерения. Это обещание: "Я уважаю твои настройки, пользователь". Никаких пикселей в корне.
Используйте
clamp()для контроля границclamp(1em, желаемое, 1.25em)— формула уважения. Мы предлагаем, пользователь располагает, но в разумных пределах.Добавляйте
vwдля плавности, но не перебарщивайте0.3vw — 0.8vwдостаточно, чтобы текст чувствовал экран, но не терял связь с пользователем.Следите за диапазоном WCAG
max <= min × 2.5— это не математика, это закон. Нарушите — и кто-то не сможет прочитать ваш текст.Стройте систему через
pow()Одна цифра (
--scale-ratio) управляет всей типографикой. Это масштабируемо, это гармонично, это профессионально.Тестируйте как пользователь
- Увеличьте масштаб до 200% — всё читается?
- Поставьте в браузере шрифт 20px — дизайн не съехал?
- Откройте на телефоне, планшете, широком мониторе — везде комфортно?
Думайте о контейнерах, не только об экране
Компоненты должны быть умными. Контейнерные запросы — ваш следующий уровень.
И напоследок
Помните: идеальный CSS — тот, который не замечаешь. Пользователь не должен думать о том, как настроить шрифт. Он просто читает, и ему комфортно.
Ваш код — это невидимый помощник, который:
- Подкладывает подушку (на телефоне текст не мельчит)
- Отодвигает стул (на мониторе не расползается)
- И главное — всегда слушается хозяина (пользовательские настройки в приоритете)
Теперь у вас есть все инструменты, чтобы написать такой код.
Благодарность и источник
Эта статья является переработкой материала «Responsive and fluid typography with Baseline CSS features» с сайта web.dev.
Оригинальная статья содержит глубокий технический разбор темы. Мы адаптировали её для более широкой аудитории: структурировали разделы, добавили практические примеры, выделили правила доступности и снабдили готовыми шаблонами для копирования.
Благодарим авторов оригинала за фундаментальную работу и вдохновение!
Часто задаваемые вопросы (FAQ)
Почему нельзя просто использовать пиксели для font-size?
Пиксели (px) — абсолютная единица. Когда вы задаёте font-size: 16px, вы говорите браузеру: "игнорируй настройки пользователя, будет ровно 16 пикселей". Это ломает доступность для людей, которым нужен более крупный текст.
Относительные единицы (em, rem) берут за основу пользовательские настройки и строят поверх них. Это единственный способ уважать предпочтения пользователя.
В чем разница между em и rem?
1remвсегда равен размеру шрифта на корневом элементе (html). Надёжно и предсказуемо.1emравен размеру шрифта родительского элемента. Может привести к каскадному умножению, если неаккуратно использовать.
Для базового размера мы используем em на корне (чтобы реагировать на настройки), а для всех остальных размеров — rem (чтобы избежать каскада).
Как проверить, соответствует ли типографика WCAG?
Самый простой способ:
- Установите в браузере базовый размер шрифта 20px (в настройках)
- Увеличьте масштаб страницы до 200%
- Проверьте, что:
- Текст не обрезается и не перекрывается
- Все элементы интерфейса доступны
- Сайт сохраняет функциональность
Если всё работает — вы молодец. Если нет — возвращайтесь к нашей статье и проверьте формулу.
Как быть с заголовками, они же должны быть крупнее?
Для заголовков мы используем типографическую шкалу через pow(). Это создаёт гармоничную систему, где все размеры математически связаны с базовым.
Главное — даже для заголовков работает правило WCAG: при масштабировании 200% они должны оставаться читаемыми. Проверяйте самый крупный заголовок на самом узком экране.
Можно ли использовать эту технику с CSS-фреймворками (Tailwind, Bootstrap)?
Tailwind: Да, просто задайте эти переменные в своём :root и используйте их в конфиге Tailwind для настройки типографики.
Bootstrap: Переопределите переменные $font-size-base и используйте нашу формулу. Bootstrap 5 активно использует CSS-переменные, что упрощает интеграцию.
Любой другой фреймворк: Принцип тот же — найдите, как в нём задаётся базовый размер шрифта, и подставьте нашу формулу.
Что делать, если нужна поддержка старых браузеров?
clamp() и pow() — современные функции. Для старых браузеров можно использовать подход с постепенной деградацией:
html {
font-size: 1.25em; /* Запасной вариант для старых браузеров */
font-size: clamp(1em, 1em + 0.5vw, 1.25em); /* Для современных */
}Старые браузеры проигнорируют второе правило и используют запасной вариант. Это не идеально, но приемлемо.
А что насчёт line-height и отступов?
Отличный вопрос! Та же логика работает и для других типографических величин:
:root {
/* Базовый размер (наша формула) */
font-size: clamp(1em, 1em + 0.5vw, 1.25em);
/* Относительные величины */
--line-height-base: 1.5; /* без единиц - относительно текущего font-size */
--spacing-base: 1rem; /* отступы, тоже масштабируются */
}
body {
line-height: var(--line-height-base);
margin-bottom: var(--spacing-base);
}Все относительные величины будут автоматически масштабироваться вместе с текстом.
Как быть с адаптивностью изображений и видео?
Медиаконтент лучше масштабировать независимо от текста. Используйте для них относительные единицы, но не привязывайте жёстко к текстовой формуле:
img, video {
max-width: 100%; /* занимают доступное пространство */
height: auto; /* сохраняют пропорции */
}Если нужно, чтобы размер медиа тоже зависел от контекста — контейнерные запросы ваш выбор.
Почему в формуле используется именно 1.25em для максимума?
Это консервативное значение, которое гарантирует запас для WCAG: 1.25 × 2 = 2.5 — ровно граница правила.
Вы можете увеличить максимум до 1.5em или даже 1.75em, но тогда тщательно проверяйте масштабирование на широких экранах. Чем больше максимум, тем меньше запас прочности.
Где можно протестировать готовое решение?
Несколько полезных инструментов:
- Chrome DevTools — эмуляция разных устройств и масштабов
- WAVE Evaluation Tool — проверка доступности
- WCAG Contrast Checker — проверка контрастности
- BrowserStack — тестирование на реальных устройствах
Но лучший тест — открыть сайт на реальном телефоне, планшете и мониторе и покрутить масштаб. Ничто не заменит живых рук и глаз.