Медиазапросы меняют макет ступенями: до порога — так, после — иначе. Но многое хочется менять плавно: чтобы заголовок подрастал вместе с шириной экрана, а контейнер не превышал разумной ширины на огромном мониторе — без единого breakpoint. Для этого в CSS есть гибкие единицы (%, vw, vh) и функции (clamp(), min(), max()), которые вычисляют размер на лету. Они делают вёрстку по-настоящему текучей и часто позволяют обойтись меньшим числом медиазапросов.
После этого урока вы сможете задавать размеры, которые плавно подстраиваются под экран, и ограничивать их разумными рамками — заголовки, отступы и контейнеры станут отзывчивыми сами по себе.
Что уже умеем / что добавим
Вы адаптируете макет медиазапросами и контейнерными запросами — ступенчато. Теперь добавим плавную адаптацию через гибкие единицы и функции. В сквозном проекте мы сделаем главный заголовок и контейнер страницы текучими: заголовок будет плавно расти, а контейнер — тянуться, но не шире разумного предела.
Что вы узнаете в рамках статьи
- Как работают относительные единицы
%,vwиvh. - Что делают функции
min()иmax(). - Как задавать «размер в рамках» функцией
clamp(). - Как плавно масштабировать текст и контейнеры без медиазапросов.
Ключевые термины
%— размер относительно родителя.vw/vh— 1% ширины / высоты окна (viewport width/height).min(a, b)— выбирает меньшее из значений.max(a, b)— выбирает большее из значений.clamp(min, идеал, max)— значение в рамках: не меньшеmin, не большеmax.
Относительные единицы: %, vw, vh
Проценты задают размер относительно родителя: width: 50% — половина ширины родительского блока. Это давно знакомо. Единицы vw и vh считают от окна: 1vw — это один процент ширины окна, 1vh — один процент его высоты.
.hero {
width: 100vw;
height: 50vh;
}
Такой блок займёт всю ширину окна и половину его высоты — и будет пересчитываться при изменении размера окна. vw/vh удобны для крупных блоков «в экран»: обложек, экранов-заставок. Проценты же чаще применяют внутри контейнеров. Обе единицы текучие: размер меняется плавно вместе с окном или родителем, без ступеней.
Функции min() и max()
Функции min() и max() выбирают из нескольких значений одно — и это мощный инструмент ограничения. Несмотря на названия, работают они чуть непривычно, поэтому разберём внимательно.
min(a, b) берёт меньшее из значений. Типичный приём — ограничить ширину сверху:
.container {
width: min(90%, 1200px);
}
Здесь ширина будет равна 90%, пока эти 90% меньше 1200px (на небольших экранах), но как только 90% превысят 1200px (на большом мониторе), возьмётся 1200px. Итог: контейнер тянется вместе с экраном, но не шире 1200px. max(a, b) работает наоборот — берёт большее, что удобно для ограничения снизу, например max(300px, 50%) не даст блоку стать уже 300px.
Функция clamp()
clamp() объединяет обе идеи и задаёт значение в рамках. Она принимает три аргумента: минимум, идеальное (обычно текучее) значение и максимум:
.title {
font-size: clamp(1.5rem, 4vw, 3rem);
}
Читается так: размер шрифта стремится к 4vw (плавно растёт с шириной окна), но никогда не станет меньше 1.5rem и больше 3rem. На узком экране заголовок не съёжится ниже полутора рем, на широком — не раздуется больше трёх, а между ними — плавно подстраивается. Это чрезвычайно удобно для «отзывчивой типографики»: один clamp() заменяет несколько медиазапросов для размера шрифта. Тот же приём применим к отступам, ширине, любым размерам, где нужна плавность в разумных границах.
Плавная адаптация без медиазапросов
Гибкие функции позволяют решать целые задачи адаптивности вообще без @media. Заголовок на clamp() масштабируется сам. Контейнер на min() сам держит максимальную ширину. Отступы можно сделать текучими:
.section {
padding: clamp(1rem, 5vw, 4rem);
}
Отступы секции плавно растут от 1rem на телефоне до 4rem на большом экране, не требуя ни одной контрольной точки. Это не значит, что медиазапросы больше не нужны — для смены самого макета (число колонок, показ/скрытие блоков) они по-прежнему главные. Но для плавного масштабирования размеров гибкие функции чище и короче: меньше кода, естественнее поведение. Профессиональная вёрстка сочетает оба подхода: ступенчатые перестройки — медиазапросами, плавное масштабирование — гибкими функциями.
Применяем в проекте
Сделаем главный заголовок и контейнер страницы текучими. Заголовок будет плавно расти с шириной экрана в разумных пределах, а контейнер — тянуться, но не шире 1200px и с текучими отступами. Всё это без медиазапросов.
.container {
width: min(90%, 1200px);
margin: 0 auto;
padding: clamp(1rem, 4vw, 3rem);
}
.hero__title {
font-size: clamp(1.75rem, 5vw, 3.5rem);
}
Плавно меняйте ширину окна: заголовок подрастает и уменьшается сам, оставаясь читаемым и не гигантским; контейнер расширяется вместе с экраном, но на большом мониторе замирает на 1200px и остаётся по центру, а его внутренние отступы мягко меняются. Мы добавили ощутимую адаптивность, не написав ни одного медиазапроса. Текучесть — признак современной, аккуратной вёрстки.
Частые ошибки
- Путаница
min()иmax().
Для ограничения ширины сверху нуженmin()(берёт меньшее), для нижней границы —max(); названия сбивают с толку, проверяйте логику. 100vwи горизонтальная прокрутка.
100vwне учитывает полосу прокрутки и может дать лишний горизонтальный скролл; для ширины по родителю чаще безопаснее100%.clamp()без разумных границ.
Слишком широкий диапазон делает текст то крошечным, то огромным; подбирайте минимум и максимум осознанно.- Отказ от медиазапросов совсем.
Гибкие функции масштабируют размеры, но не перестраивают макет; смену числа колонок оставляйте за@media.
Итоги
Прекрасная работа — ваша вёрстка стала текучей! Вы освоили относительные единицы %, vw и vh, разобрались с функциями min() и max() для ограничения размеров и научились задавать значение в рамках через clamp(). Теперь заголовок и контейнер вашего сайта плавно подстраиваются под экран без единого медиазапроса — это признак зрелой, современной вёрстки.
Отличный прогресс! Впереди — заключительный урок курса: мы займёмся адаптивными изображениями и авто-сетками, научимся вписывать картинки через object-fit и aspect-ratio и строить сетки, которые сами меняют число колонок с auto-fit и auto-fill.