Когда в CSS использовать rem, em, px, или что-то другое

Использование только px (пикселей) для CSS-размеров шрифта, контейнеров, отступов, позиционирования и пр. – путь простой, но тупиковый.

  • %, fr и flex-grow – эти единицы измерения лучше использовать для установки размеров контейнерам
  • px лучше использовать для установки размеров декоративных элементов, например, border
  • для определения высоты строки (line-height) лучше вообще не использовать единицы измерения и оставить только число
  • rem – для всего остального: размеров шрифта, полей, отступов, минимальной ширины и точек @media

Что такое rem?

rem (как и em) относительная единица измерения. em может быть немного сложным в использовании, поэтому часто лучше придерживаться rem. Вот как rem работает:

  • rem – это единица измерения, относительно размеров корневого элемента («r» в rem означает: root).
  • Допустим, браузер считает базовый размер шрифта 16px. Этот размер указан для корневого элемента (он же элемент html)

Таким образом, если нужно, чтобы какой-то размер был эквивалентен 14px, достаточно посчитать его отношение к базовому размеру: 14/16 = 0.875rem.

Почему rem?

Относительные единицы предпочтительнее пикселей, потому что они учитывают предпочтения пользователя и настройки его браузера. Браузер позволяет пользователю изменить размер шрифта по умолчанию. Это значение применяется к размеру шрифта по умолчанию для корневого элемента. Поскольку rem вычисляется относительно размера основного шрифта, то размеры, указанные в rem будут пропорционально масштабироваться.

Таким образом, rem можно использовать практически для всех случаев. Например, для: font-size, margin, padding, min-width и т.д.

Есть ли у rem какие-либо недостатки?

Использование rem в медиа-запросах (@media), для минимальной или максимальной ширины, может быть проблематичным из-за того, что браузеры использует разные методы округления дробных чисел.

Но настоящий недостаток, это неинформативность дробных относительных значений и необходимость их пересчета, чтобы осознать размер в привычных пикселях. Например, при просмотре кода не очевидно, что min-width: 18.75rem это – 300px из макета. Немного поправить эту проблему можно, реализуя в препроцессоре функцию, которая будет выполнять вычисления и поможет прояснить, что происходит. В SCSS это может быть так:

$base-font-size: 16;

// strips away any unit from a value: e.g. "16px" => 16
@function strip-unit($number) {
  @if type-of($number) == 'number' and not unitless($number) {
    @return $number / ($number * 0 + 1);
  }
  @return $number;
}

@function px-to-rem($size, $base: $base-font-size) {
  $pxUnitless: strip-unit($size);
  @return #{$pxUnitless / $base}rem;
}

.some-selector {
  font-size: px-to-rem(20);
  padding: px-to-rem(14) px-to-rem(32);
}

Когда использовать px?

Чем реже – тем лучше. Пиксели следует использовать, когда размеры являются декоративными и/или не нуждаются в масштабировании относительно, предпочитаемого пользователем, размера шрифта. Отличный вариант использования px – границы (border). Чаще всего нет необходимости масштабировать их относительно размеров шрифта.

Как насчет %, fr, flex-grow?

Контейнерные элементы – это те, которые содержат контент. Это прямоугольники, которые содержат текст, изображения и другие элементы контейнера. Они обычно нуждаются в указании размеров и расположения. Размеры контейнерных элементов следует указывать с использованием относительных значений: проценты, fr (для CSS grid) или flex-grow (для flexbox). Это гарантирует, что элемент контейнера будет изменять свои размеры относительно размеров окна браузера.

При настройке размеров элемента с использованием относительных значений можно указать, что они не будут меньше, какого-либо значения. В этом случае можно указывать минимальные размеры с помощью rem.

.row {
  display: flex;
}

/* 4 column layout */
.column {
  min-width: 18.75rem; /* 300px */
  width: 25%;
}

Когда единицы измерения можно не указывать?

Из всего сказанного до сих пор, есть одно исключение: line-height (высота строки).

Лучше определять значение line-height относительно размера шрифта элемента font-size. Сделать это можно полным отсутствием единиц измерения. Например, если нужно, чтобы font-size составлял 14 пикселей, а line-height 20 пикселей, посчитать можно так:

  • font-size – это значение в пикселях, которое делим на размер корневого шрифта (= 14/16)
  • line-height будет равен желаемому значению в пикселях, деленному на размер шрифта в пикселях = 20/14
.small {
  font-size: 0.875rem; /* 14px / 16px */
  line-height: 1.4285714286; /* 20px / 14px */
}