Разбор единиц измерения CSS: px, rem, em, vh — и когда использовать каждую
Выбор неправильной единицы измерения CSS приводит к тому, что верстка ломается на разных экранах, шрифты игнорируют предпочтения пользователя, а отступы кажутся непоследовательными. Перед вами практическое руководство по выбору правильной единицы каждый раз.
Почему важны единицы измерения в CSS
В CSS существует более дюжины единиц длины, но большинство разработчиков на практике используют пять: px, rem, em, %, а также единицы вьюпорта vh и vw. Ошибка в выборе не всегда очевидна — макет может отлично отображаться на вашем экране и «разваливаться» на чьем-то другом, или пройти визуальное тестирование (QA), но провалить аудит доступности из-за игнорирования настроек размера шрифта пользователя в браузере.
В этом руководстве объясняется, что именно измеряет каждая единица, даются конкретные правила выбора для каждой ситуации и рассматриваются ошибки, которые постоянно встречаются в код-ревью.
px — Абсолютные пиксели
Один CSS px отображается на один независимый от устройства пиксель, а не обязательно на физический пиксель экрана. На дисплее Retina с плотностью 2x один CSS px отрисовывается с использованием 2 физических пикселей. Это означает, что px стабильны во всех экранах с точки зрения визуального размера, но они абсолютны — они не масштабируются ни с чем.
Когда использовать px:
- Границы (borders):
border: 1px solid— граница в 1px всегда должна выглядеть как тонкая линия, независимо от контекста - Тени и контуры (box shadows and outlines): детали точности, которые не должны масштабироваться
- Точки останова медиа-запросов:
@media (min-width: 768px) - Декоративные элементы с фиксированным размером (иконки с определенным размером, разделители)
Когда не использовать px: размеры шрифтов, отступы (padding) и поля (margin). Пользователь, установивший размер шрифта в браузере на 20px из-за трудностей с чтением мелкого текста, не получит никакой пользы от вашего макета, если всё жестко прописано в px. Его предпочтение будет полностью проигнорировано.
rem — Root Em
<rem сокращается как «root em». Она всегда относительна к <font-size> элемента <html>, а не к родителю. Это делает её предсказуемой в тех ситуациях, где <em> не гарантирует такого поведения.
По умолчанию большинство браузеров устанавливают базовый размер шрифта в 16px. Таким образом:
1rem = 16px | 1.5rem = 24px | 0.875rem = 14px
Когда использовать rem:
- Размеры шрифтов — rem учитывает предпочтения пользователя в настройках браузера
- Отступы, которые должны пропорционально масштабироваться вместе с размером текста (padding, margin, gap)
- Размеры компонентов, когда вы хотите, чтобы всё масштабировалось вместе
Хитрость 62.5%: Некоторые разработчики устанавливают <html { font-size: 62.5%; }>, чтобы сделать 1rem равным 10px (так как 62.5% от 16px = 10px). Это упрощает ментальные вычисления: <1.4rem = 14px. Минус в том, что это переопределяет базовое предпочтение шрифта пользователя, если не использовать этот метод с осторожностью — делайте это только в том случае, если понимаете последствия для доступности и используете переопределение на уровне компонентов.
em — Относительно родителя
<em относительна к вычисленному размеру шрифта текущего элемента (или к родителю, когда применяется к самому свойству font-size). Это делает её полезной для компонентов, которым нужно масштабироваться пропорционально их собственному размеру текста.
Классический пример использования: отступы кнопки (button padding). Если вы напишете <padding: 0.5em 1em, отступы кнопки будут автоматически масштабироваться при изменении размера шрифта кнопки — маленькие кнопки получат меньшие отступы, большие — большие.
.btn { font-size: 1rem; padding: 0.5em 1em; }
.btn-lg { font-size: 1.25rem; /* padding масштабируется автоматически */ }
Проблема наслоения (compounding): Когда вы вкладываете элементы с размерами шрифта em, они умножаются. Родитель на <1.2em и ребенок на <1.2em дадут ребенку эффективный размер <1.44em>. Именно поэтому для размеров шрифтов в большинстве случаев предпочтительнее rem — rem всегда ссылается на корень, поэтому вложенность не вызывает накопления значений.
Когда использовать em: отступы (padding), поля (margin) и межстрочный интервал (line-height) в компонентах, где вы хотите, чтобы размеры следовали за собственным размером шрифта компонента. Избегайте em для размеров шрифтов во вложенных компонентах.
% — Процент
Процент всегда относительно соответствующего измерения родительского элемента. Проценты ширины относительны к ширине родителя; проценты высоты относительны к высоте родителя (с оговорками).
Это особенно полезно для адаптивных макетов: <width: 100% означает «занимай всю доступную ширину». В сочетании с max-width это создает адаптивные контейнеры:
.container { width: 100%; max-width: 1200px; margin: 0 auto; }
Для размера шрифта процент работает как em — он умножается на родителя. Для более предсказуемых результатов используйте rem вместо него.
vh, vw — Единицы вьюпорта
<1vh = 1% высоты вьюпорта. <1vw = 1% ширины вьюпорта. Они не зависят от каких-либо элементов — они всегда относятся к размеру окна браузера.
Когда использовать единицы вьюпорта:
- Полноэкранные секции: <
height: 100vhдля hero-блока, который занимает экран полностью - Адаптивная типографика: <
font-size: clamp(1rem, 2.5vw, 2rem)для текста, который плавно масштабируется между размерами экранов без медиа-запросов - Изображения или видео во всю ширину: <
width: 100vw, чтобы выйти за пределы контейнера
Проблема мобильной панели браузера: В мобильных браузерах адресная строка появляется и исчезает при скролле, изменяя высоту вьюпорта. <100vh может привести к обрезанию контента или появлению полос прокрутки. CSS добавил <dvh (динамическая высота вьюпорта), <svh (малая — адресная строка видна) и <lvh (большая — адресная строка скрыта) для решения этой проблемы. Поддержка dvh хороша в 2024+. Используйте <height: 100dvh для полноэкранных макетов на мобильных устройствах.
Руководство по выбору единиц CSS
| Что вы масштабируете | Используйте это | Почему |
|---|---|---|
| Основной / глобальный размер шрифта | rem | Учитывает предпочтения пользователя, нет накопления |
| Размер шрифта компонента | rem | Согласованно, предсказуемо |
| Отступы компонентов (padding / margin) | em или <rem> | em если хотите связь с font-size; rem для согласованности |
| Границы, тени (borders, box-shadows) | px | Никогда не должны масштабироваться |
| Точки останова медиа-запросов | px или <em> | px для простоты; em так, чтобы точки останова масштабировались с предпочтениями шрифтов |
| Адаптивная ширина контейнера | <% + <max-width> | Занимает доступное пространство, ограничивается максимумом |
| Полноэкранная секция (hero) | <100dvh> | Учитывает мобильные панели браузера |
| Адаптивная типографика | <clamp() с rem + vw | Плавно масштабируется между точками останова |
Самые распространенные ошибки
1. Использование px для всех размеров шрифтов. Это нарушает доступность. Пользователи, увеличивающие базовый размер шрифта в браузере, обнаружат, что ваш текст не изменился. Используйте rem для размеров шрифтов, чтобы интерфейс учитывал эти настройки.
2. Использование em для размеров шрифтов во вложенных компонентах. Здесь проявляется проблема накопления. Меню внутри карточки внутри модального окна может получить 3-кратное умножение. Используйте rem для размеров шрифтов.
3. Использование vh для полноэкранных макетов без fallback на dvh. На мобильных устройствах адресная строка вызывает смещение макета. Используйте <min-height: 100svh или <height: 100dvh>.
4. Забывание о том, что процентная высота требует родителя с явной высотой. <height: 100% у дочернего элемента не подействует, если у родителя установлено <height: auto>. Используйте <vh> или Flexbox вместо этого.
Формула конвертации px → rem
Стандартный базовый размер шрифта — 16px. Формула для конвертации:
Пример: <
24px ÷ 16 = 1.5rem
Если вы работаете с инструментом дизайна, который выдает пиксели, наш Конвертер PX в REM мгновенно выполнит расчеты. Вставьте любое значение px (или список значений) и получите эквивалент в rem с поддержкой пользовательских базовых размеров.
Мгновенно конвертировать px в rem
Вставьте любое значение в пикселях и получите эквивалент в rem. Поддерживает пользовательские базовые размеры шрифтов.