Menu

Единицы CSS: rem, em и px, проценты, vw и vh

rem считается от размера шрифта корневого элемента, em от размера шрифта текущего элемента, px фиксирован, а % зависит от свойства. Посмотрите на каждую единицу с замером во вложенном примере, почему em перемножается, когда что использовать и как работают vw, vh и dvh.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

rem и em на одном вложенном примере

rem считается от корневого размера шрифта (элемент <html>, по умолчанию 16px). em считается от текущего размера шрифта, а для font-size это размер родителя. Вложите один и тот же класс три раза, и разница станет видна:

Выведенные размеры вычислил браузер. Каждый 1.25em умножает размер родителя: 20px, затем 25px, затем 31.25px. Каждый 1.25rem смотрит только на корень: 20px, 20px, 20px. Из-за такого перемножения размеры шрифта в em выходят из-под контроля во вложенных списках и меню, и поэтому большинство сайтов задают размеры шрифта в rem.

От чего считается каждая единица

ЕдиницаСчитается от1 единица по умолчанию
pxни от чего (пиксель CSS)1px
remразмера шрифта корневого элемента (html)16px
emразмера шрифта элемента; для самого font-size от размера родителя16px на верхнем уровне
%зависит от свойства (смотрите ниже)
vw / vh1% ширины / высоты окна просмотра
dvh, svh, lvh1% динамической, малой или большой высоты окна просмотра
vmin / vmax1% меньшей / большей стороны окна просмотра
chширины «0» в текущем шрифтеоколо половины em
exвысоты строчной буквы x в текущем шрифтеоколо половины em

Пиксель CSS это не пиксель устройства: на телефоне с экраном 3x 1px занимает 3 пикселя устройства. Визуально он примерно одинаков на разных экранах, поэтому px по-прежнему хорош для рамок и теней.

em для отступов, которые масштабируются с текстом

em нужен не только для размеров шрифта. В padding, margin, width или border-radius он означает «умножить на размер шрифта этого элемента». Так один класс кнопки работает при любом размере:

Padding каждой кнопки по вертикали равен половине ее размера шрифта, а по горизонтали одному размеру шрифта, поэтому три кнопки выглядят как одна и та же кнопка в трех размерах. С padding в px понадобилось бы отдельное правило для каждого размера.

Учтите, что кнопки по умолчанию не наследуют размер шрифта страницы (браузеры дают элементам форм свой), поэтому средняя кнопка здесь в Chrome 13.33px, а не 16px. Добавьте кнопкам и полям font: inherit, если хотите, чтобы они совпадали со страницей.

Проценты: зависит от свойства

У % нет единого смысла. Каждое свойство определяет, от чего берутся его проценты:

Свойство% считается от
width, max-width, left, rightширины родителя (содержащего блока)
height, top, bottomвысоты родителя, и только если у родителя задана высота
padding, margin (все четыре стороны)ширины родителя
font-sizeразмера шрифта родителя (150% = 1.5em)
line-heightсобственного размера шрифта элемента
transform: translate()собственного размера элемента

width: 50% это 200px, половина родителя. padding-top: 5% это 20px: 5% от ширины родителя, а не от высоты. А height: 50% ничего не делает, потому что у родителя нет заданной высоты, и дочерний элемент высотой только с текст плюс этот padding. Это правило подробно разобрано на странице про width и height.

vw, vh и адресная строка на телефонах

1vw это 1% ширины окна просмотра, а 1vh 1% его высоты. Они полезны для полноэкранных секций и плавных размеров (часто внутри clamp()). На телефонах у vh есть подвох: адресная строка браузера выезжает и прячется при прокрутке, а 100vh это высота без строки, поэтому шапка с height: 100vh обрезается снизу, когда строка видна. Новые единицы это исправляют:

ЕдиницаКакая высота используется
100vhбольшое окно просмотра (панели скрыты) в большинстве мобильных браузеров
100svhмалое окно просмотра (панели видны): всегда помещается
100lvhбольшое окно просмотра, явно
100dvhдинамическое окно просмотра: меняется, когда панели двигаются
.hero {
  min-height: 100vh;  /* fallback for older browsers */
  min-height: 100svh; /* fits the screen even with the address bar visible */
}

У vw свой подвох: 100vw включает ширину вертикальной полосы прокрутки, когда полоса занимает место (как в Windows), поэтому width: 100vw может оказаться шире страницы и добавить горизонтальную прокрутку. Для «всей ширины родителя» используйте width: 100%.

ch для удобной длины строки

ch это ширина символа «0», поэтому max-width: 65ch ограничивает абзац примерно 65 символами в строке, удобной для чтения длиной, при любом размере шрифта:

Какую единицу выбрать

Для чегоЧто использоватьПочему
Размеры шрифтаremОдинаков везде, учитывает настройку размера шрифта читателя
Padding и промежутки в компонентахrem или emem, когда должен расти вместе с текстом самого компонента
Рамки, тонкие линии, тениpxДолжны оставаться тонкими при любом размере шрифта
Ширины раскладки%, fr, max-width в rem или chСледуют контейнеру, ограничивают длину строки
Полноэкранные секцииsvh / dvh (с запасным vh)Учитывают адресную строку на телефонах
Плавная типографикаclamp() с сочетанием rem и vwРастет вместе с экраном в пределах границ

Почему rem уважает читателей, а px нет

В браузерах есть настройка размера шрифта по умолчанию, ей пользуются люди, которым нужен более крупный текст. Она меняет корневой размер шрифта, поэтому все в rem и em растет вместе с ней. font-size: 14px остается 14px, что бы ни выбрал читатель. Масштаб браузера увеличивает и px, но многие читатели полагаются именно на настройку размера шрифта. Это главная причина задавать размеры шрифта в rem.

Некоторые сайты задают html { font-size: 62.5%; }, чтобы 1rem равнялся 10px и считать было проще. Это по-прежнему учитывает настройку читателя (62.5% от выбранного им значения), но не забудьте задать удобный для чтения font-size на body, иначе каждый элемент без собственного размера покажет текст 10px.

Частые ошибки

  • Размеры шрифта в em во вложенных элементах. Они перемножаются на каждом уровне. Для размеров шрифта используйте rem.
  • height: 50%, который ничего не делает. Чтобы процентная высота работала, родителю нужна заданная высота.
  • Ожидание, что padding-top: 10% будет считаться от высоты родителя. Проценты вертикальных padding и margin считаются от ширины родителя.
  • width: 100vw вызывает горизонтальную прокрутку. Он включает полосу прокрутки. Используйте 100%.
  • height: 100vh обрезается на телефонах. Используйте 100svh или 100dvh.
  • html { font-size: 12px }. Значение в px на корне перебивает настройку размера шрифта читателя для всей страницы. Не трогайте корень или используйте проценты.

Часто задаваемые вопросы

Чем rem отличается от em?

rem считается от размера шрифта корневого элемента (<html>), поэтому 1.5rem одинаков везде на странице. em считается от размера шрифта самого элемента (для font-size от размера родителя), поэтому при вложении элементов он перемножается.

Сколько пикселей в 1rem?

По умолчанию 16px, потому что браузеры задают корневому элементу размер шрифта 16px. Если пользователь увеличит размер шрифта по умолчанию в настройках браузера или вы зададите html { font-size: ... }, 1rem изменится вместе с ним.

Что использовать для размера шрифта: rem или px?

Для размеров шрифта используйте rem. Он учитывает настройку размера шрифта по умолчанию в браузере читателя, которую px игнорирует. Масштаб браузера увеличивает оба, но не каждый читатель пользуется масштабом.

Когда использовать em, а не rem?

em для отступов, которые должны масштабироваться вместе с текстом самого элемента, например padding кнопки или размер иконки рядом с текстом. Тогда один класс выглядит правильно при любом размере шрифта. rem для размеров шрифта и отступов на уровне страницы, чтобы ничего не перемножалось.

Чем 100vh отличается от 100dvh?

100vh в мобильных браузерах это высота со скрытой адресной строкой, поэтому секция 100vh выше видимого экрана, пока строка показана. 100dvh (динамическая высота окна просмотра) следует за строкой, когда она появляется и исчезает, а 100svh всегда меньшая высота.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ