← назад к разделу

В 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: адаптивность, встроенная в раскладку.
  • Блочная модель — как единицы складываются в размер коробки.
  • Оформление: градиенты, тени и трансформации — финальная тема цикла.