В CSS десятки единиц измерения, но осмысленный выбор — между пятью-шестью. От выбора зависит не красота кода, а поведение: отмасштабируется ли интерфейс у пользователя с крупным шрифтом, переживёт ли компонент перенос в другой контекст, сколько медиазапросов придётся написать. Разберём рабочий набор.
px, rem, em: три системы отсчёта
px — абсолютная единица. Предсказуемая, но глухая к настройкам пользователя: если в браузере выставлен крупный шрифт по умолчанию, px-размеры не отреагируют.
rem — доля корневого размера шрифта (по умолчанию 16px, меняется настройкой браузера). 1.5rem = 24px у большинства, но честно вырастет у того, кто настроил крупнее. Правило современных проектов: размеры шрифтов — только в rem; отступы и радиусы — rem или px по вкусу команды (rem даст масштабирование всей сетки вместе с текстом).
em — доля размера шрифта текущего элемента. Коварна каскадным умножением (em внутри em внутри em), но незаменима локально: padding кнопки в em растёт вместе со шрифтом кнопки — компонент масштабируется одной правкой font-size. Практический дуэт: глобальное — rem, внутрикомпонентное — em, точная графика — px.
Есть и контентные единицы: ch — ширина цифрового символа, идеальна для ограничения длины строки текста (max-width: 65ch), и lh — высота строки.
Проценты: главное — от чего
Процент всегда считается от чего-то у родителя, и «от чего» зависит от свойства:
width: 50%— от ширины родителя;height: 100%— от высоты родителя, но только если она задана явно (иначе игнорируется — знаменитое «height: 100% не работает»);paddingиmarginв процентах — от ширины родителя, даже вертикальные (исторический факт);font-size: 120%— от шрифта родителя (синоним 1.2em);transform: translateX(50%)— от размера самого элемента (потому центрирование абсолютного элемента — этоleft: 50%+translateX(-50%): первый процент от родителя, второй от себя).
Половина «не работающих» процентов — неверная догадка о базе отсчёта.
Вьюпорт-единицы: vw, vh и их мобильные наследники
1vw/1vh — процент ширины/высоты окна. Полноэкранные секции (min-height: 100vh), элементы «во весь экран» независимо от родителей. Плюс производные vmin/vmax.
Мобильная боль: панель браузера то прячется, то выезжает — «высота окна» меняется, и 100vh то с прокруткой, то с прыжком. Ответ спецификации — три семейства: svh (маленький вьюпорт — панель видна), lvh (большой — панель скрыта), dvh (динамический — следит за фактом). Для полноэкранных блоков сегодня пишут min-height: 100dvh с фолбэком 100vh строкой выше.
clamp: резиновое значение с ограничителями
Функция, съевшая половину медиазапросов:
h1 { font-size: clamp(1.5rem, 1rem + 2.5vw, 2.5rem); }
clamp(мин, желаемое, макс) — желаемое значение зависит от ширины окна (за счёт vw), но зажато границами. Заголовок плавно растёт от телефона к монитору без единого брейкпоинта. Та же техника — для отступов секций (padding-block: clamp(2rem, 5vw, 6rem)) и ширин. Смесь rem + vw в средней части важна: чистый vw не масштабируется настройкой шрифта пользователя, добавка rem возвращает эту связь.
Рядом — min() и max(): width: min(90%, 1200px) — «на всю ширину, но не шире контейнера» одной строкой, без max-width.
Медиазапросы: что осталось на их долю
Автосетки grid, переносы flexbox и clamp закрывают массу «адаптивности» сами. Медиазапросы остаются для структурных перестроек: спрятать сайдбар, превратить меню в бургер, переставить grid-области.
.layout { display: grid; grid-template-columns: 1fr; }
@media (min-width: 768px) {
.layout { grid-template-columns: 240px 1fr; }
}
Рабочий подход — mobile-first: базовые стили для узкого экрана, min-width-запросы наращивают сложность. Брейкпоинты привязывают не к «айфонам», а к контенту: где макет ломается — там и порог. Кроме ширины полезны (hover: hover) — отличить устройства с курсором (hover-эффекты только там), и prefers-reduced-motion / prefers-color-scheme — уважение к настройкам пользователя. А для компонентов, которые должны реагировать на ширину своего контейнера, а не окна, появились container queries — @container — следующий шаг той же идеи.
Коротко
- Шрифты — в rem (уважение к настройкам пользователя), внутрикомпонентные отступы — em, точная графика — px, длина строки — ch.
- Проценты считаются от разного: width — от ширины родителя, height — только от явной высоты, padding/margin — всегда от ширины, translate — от самого элемента.
- Полноэкранная высота на мобильных —
100dvh(с фолбэком 100vh): обычный vh прыгает из-за панели браузера. clamp(мин, rem+vw, макс)— резиновые типографика и отступы без брейкпоинтов;min(90%, 1200px)— контейнер одной строкой.- Медиазапросы — для структурных перестроек, mobile-first, пороги от контента;
hover: hoverи prefers-* — про устройства и людей, не про пиксели.
Что почитать дальше
- Grid — auto-fit/minmax: адаптивность, встроенная в раскладку.
- Блочная модель — как единицы складываются в размер коробки.
- Оформление: градиенты, тени и трансформации — финальная тема цикла.