Плавные макеты без точек прерыва
Создание полностью плавных интерфейсов с использованием современных CSS-технологий.
Почему стоит переосмыслить точки прерыва?
Классический адаптивный дизайн опирается на серию медиа-запросов, которые переводят макет из одной фиксированной конфигурации в другую. Хотя этот адаптивный подход работает, он вызывает ряд повторяющихся проблем:
- Поддержка нескольких дизайнов: Каждая точка прерыва фактически является отдельным макетом для тестирования и поддержки.
- Мёртвые зоны: между точками прерыва дизайн может казаться растянутым, сжатым или иным образом неоптимальным.
- Сложности масштабирования: новые ширины устройств или встроенные контексты (панели, iframe) быстро выявляют пробелы в покрытии.
Современный CSS предлагает инструменты, позволяющие создать непрерывно плавные интерфейсы — такие, которые изящно адаптируются при каждом изменении ширины без явных точек прерыва.
Основные компоненты плавного дизайна
- Плавающие единицы (%,
vw,vh,vmin,vmax) - Функции, зависящие от области просмотра (
clamp(),min(),max(),calc()) - Встроенная размерность (
min-content,max-content,fit-content) - Гибкие режимы макета (Flexbox, Grid)
- Контейнерные запросы для по-настоящему контекстно-зависимых компонентов
Плавная типографика с clamp()
Функция clamp() позволяет задавать размер шрифта, который плавно увеличивается с ростом области просмотра, при этом сохраняя разумные пределы.
html {
font-size: clamp(1rem, 0.4rem + 1.2vw, 1.75rem);
}
Эта одна строка заменяет несколько медиа-запросов. Размер шрифта:
- Никогда не уменьшается ниже
1rem. - Масштабируется с
1.2vwпо большей части ширин. - Ограничивается комфортным
1.75remдля очень широких экранов.
Плавное пространство и размеры
В том же духе отступы, поля, зазоры и даже радиусы границ могут масштабироваться плавно:
:root {
--space-s: clamp(0.5rem, 0.2rem + 0.6vw, 1rem);
--space-l: clamp(1rem, 0.4rem + 1.2vw, 2rem);
}
.card {
padding: var(--space-l);
gap: var(--space-s);
}
Использование пользовательских свойств позволяет держать математику в одном месте и обеспечивает последовательное соотношение при изменении области просмотра.
Фракционный Flexbox и автоматическая переносимость
Flexbox отлично подходит для одномерной плавности. Комбинируя ширины в процентах с flex: auto (или просто flex: 1), можно получить строки, которые заполняются, растягиваются и переносятся естественным образом:
.toolbar {
display: flex;
flex-wrap: wrap;
gap: clamp(0.25rem, 0.1rem + 0.5vw, 0.75rem);
}
.button {
flex: 1 1 clamp(6rem, 20%, 12rem);
}
Каждая кнопка на панели пытается занимать 20 % строки, но никогда не сжимается ниже 6 рем или не растягивается выше 12 рем. Точки прерыва не требуются.
Grid с auto-fit, auto-fill и minmax()
CSS Grid открывает двумерную плавность. Распространённый шаблон — адаптивная сетка карточек:
.cards {
display: grid;
gap: var(--space-l);
grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}
Объяснения:
auto-fitзаполняет столько колонок, сколько поместится.minmax()гарантирует минимальную ширину каждой карточки 18 рем — или 100 %, если строка уже узкая.1frпозволяет карточкам равномерно расширяться при наличии дополнительного пространства.
Результат: колонки появляются и исчезают непрерывно в зависимости от доступного пространства, полностью независимо от заранее определённых точек прерыва.
Соотношение сторон без медиа-запросов
С помощью свойства aspect-ratio заполнитель и изображения могут автоматически сохранять пропорции:
.video-thumbnail {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
Контейнерные запросы: недостающий элемент
Плавные техники прекрасно работают на уровне страницы, но компоненты часто располагаются внутри неизвестных контейнеров, таких как боковые панели или разделённые части. Контейнерные запросы решают это, позволяя элементам реагировать на размер их собственного контейнера, а не области просмотра:
.card {
container-type: inline-size;
}
@container (min-width: 30rem) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
Поскольку контейнерные запросы можно выразить также для диапазонов (min-width, max-width), а не только для равенств, вы можете всё равно установить точки прерыва. Однако, при использовании с встроенной размерностью и функциями области просмотра, зачастую достаточно одного контейнерного запроса — или вообще без них.
Максимальные ширины, зависящие от контента
Плавные макеты лучше всего работают, когда они учитывают читаемую длину строки. Вместо произвольных точек прерыва используйте max-inline-size или старый max-width:
main {
max-inline-size: 65ch; /* около 65 символов в строку */
margin-inline: auto;
padding-inline: var(--space-l);
}
Мера остаётся комфортной, а боковые зазоры и свободное пространство растягиваются плавно.
Когда всё-таки нужны медиа-запросы?
Обещание нулевых точек прерыва — это цель. Однако некоторые сценарии всё ещё выигрывают от классических медиа-запросов:
- Загрузка альтернативных ресурсов (например, изображение высокого разрешения при ширине более 1440 px).
- Оптимизация для грубых указателей или темной темы (
prefers-color-scheme). - Запасные решения для устаревших браузеров.
Тем не менее, для структурной раскладки большинства современных интерфейсов плавные техники могут практически полностью устранить необходимость в точках прерыва.
Заключение
Теперь у нас есть CSS-примитивы, которые масштабируются линейно, плавно растягиваются и учитывают внутренний контент. Делая ставку на clamp(), CSS Grid, Flexbox и контейнерные запросы, вы можете создавать интерфейсы, которые ощущаются как точно подобранные под каждый размер области просмотра, без написания ни одного медиа-запроса.
Результат: меньше кода, меньше проблем с поддержкой и пользовательский опыт, оставшийся целостным и удобным при любом размере.


