Возможно, вы встречали термин «R.E.M.» когда слушали радио или магнитолу… Я к тому что есть такая музыкальная группа. Еще этой аббревиатурой названа одна из фаз сна (Rapid Eye Movement). В CSS rem означает «root em». И он позволит вам достичь гармоничного и сбалансированного дизайна.

В соответствии со спецификацией W3C определение для rem:

Равен вычисленному значению font-size для корневого элемента. При указании в свойстве font-size корневого элемента единицы rem относятся к начальному значению свойства.

Это означает, что 1rem равен размеру шрифта HTML-элемента (который для большинства браузеров имеет значение по умолчанию 16 пикселей).

REM против EM

Основная проблема с модулями em заключается в том, что они связаны с размером шрифта их собственного элемента. Как таковые они могут каскадироваться и вызывать неожиданные результаты. Давайте рассмотрим следующий пример, где мы хотим, чтобы списки имели размер шрифта 12px, в случае, когда размер корневого шрифта равен 16px по умолчанию:

html {
font-size: 100%;
}

ul {
font-size: 0.75em;
}

Если у нас есть список, вложенный в другой список, размер шрифта внутреннего списка будет 75% от размера его родителя (в данном случае 9px). Мы все еще можем преодолеть эту проблему, используя что-то вроде этого:

ul ul {
font-size: 1em;
}

Это работает, однако мы все еще должны обращать внимания на ситуации, когда вложение становится еще глубже. С блоками rem все проще:

html {
font-size: 100%;
}

ul {
font-size: 0.75rem;
}

Поскольку на все размеры ссылается размер корневого шрифта, больше нет необходимости описывать случаи вложения в отдельных объявлениях.

Определение размера шрифта с помощью Rem

Одним из пионеров использования rem-модулей для определения размера шрифта является Джонатан Снук (Jonathan Snook) со своей статьей «Изменение размера шрифта с помощью REM», опубликованной еще в мае 2011 года. Как и многим другим разработчикам CSS, ему пришлось столкнуться с проблемами, возникающими в сложных макетах.

В то время старые версии IE по-прежнему имели большую долю рынка и не могли масштабировать текст, который был измерен в пикселях. Однако, как мы видели ранее, очень легко потерять след вложенности и получить неожиданные результаты с единицами em.

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

  • 10px = 0.625rem
  • 12px = 0.75rem
  • 14px = 0.875rem
  • 16px = 1rem (base)
  • 18px = 1.125rem
  • 20px = 1.25rem
  • 24px = 1.5rem
  • 30px = 1.875rem
  • 32px = 2rem

Как видим, эти значения не очень удобны для проведения расчетов. По этой причине Snook использовал трюк под названием «62,5%». В любом случае, это не было новым открытием, так как оно уже использовалось с модулями em:

body { font-size:62.5%; } /* =10px */
h1 { font-size: 2.4em; } /* =24px */
p { font-size: 1.4em; } /* =14px */
li { font-size: 1.4em; } /* =14px? */

Поскольку единицы измерения rem относятся к корневому элементу, вариант решения Snook:

html { font-size: 62.5%; } /* =10px */
body { font-size: 1.4rem; } /* =14px */
h1 { font-size: 2.4rem; } /* =24px */

Также нужно было учитывать другие браузеры, которые не поддерживали rem. Таким образом, код выше на самом деле был бы написан так:

html {
font-size: 62.5%;
}

body {
font-size: 14px;
font-size: 1.4rem;
}

h1 {
font-size: 24px;
font-size: 2.4rem;
}

Хотя это решение кажется близким к статусу «золотого правила», есть люди, которые советуют не использовать его слепо. Гарри Робертс пишет свой взгляд на использование бэков. По его мнению, хотя решение на 62,5% упрощает вычисления (поскольку размеры шрифта в пикселях в 10 раз превышают значения rem), в конечном итоге оно заставляет разработчиков явно переписывать все размеры шрифтов на своем веб-сайте.

Третье мнение исходит от Криса Койера из CSS-Tricks. Его решение использует все три метода, которые мы рассмотрели. Он сохраняет размер корня, определенный в px, модули, определенные rem, и элементы внутри модулей, размер которых равен em. Этот подход облегчает манипулирование глобальным размером, который масштабирует тип в модулях, в то время как содержимое модуля масштабируется на основе самого размера шрифта модуля. В приведенном ниже примере вы можете увидеть, как будет выглядеть подход Криса:

See the Pen One Method for Using ems and rems in CSS by SitePoint (@SitePoint) on CodePen.light

На практике существуют основные структуры, такие как Bootstrap 4 и руководящие принципы проектирования материалов, в которых используются единицы измерения rem для определения размера текстового содержимого.

Особо следует упомянуть Material-UI, очень популярную коллекцию компонентов React. Они не только одинаково изменяют размер текста, но и предлагают механизм для реализации «10px simplification», которое мы упоминали выше.

Другой недавний проект Every Layout очень вдохновенно объединяет единицы em и rem. Он ближе всего подходит к схеме модели Криса Койера и использует единицы em для выделения встроенных элементов, таких как значки SVG, пролеты или другие подобные элементы.

Как видите, решения «серебряной пули» не существует. Возможные комбинации ограничены только воображением разработчиков.

Использование rem с точками останова Media Query

Использование модулей em или rem внутри медиа-запросов тесно связано с понятием «оптимальной длины строки» и тем, как оно влияет на восприятие чтения. В сентябре 2014 года журнал Smashing Magazine опубликовал комплексное исследование веб-типографики под названием «Размер имеет значение: балансировка длины строки и размера шрифта в адаптивном веб-дизайне». Среди многих других интересных вещей, в статье дают оценку оптимальной длины строки: от 45 до 75-85 символов (включая пробелы и знаки пунктуации), с 65 «идеальным» целевым значением.
Используя приблизительную оценку 1rem = 1 символ, мы можем управлять потоком текста для одного столбца контента в подходе, ориентированном на мобильные устройства:

.container {
width: 100%;
}

@media (min-width: 85rem) {
.container {
width: 65rem;
}
}

Однако есть одна интересная деталь о единицах rem и em при использовании в качестве единиц для медиазапросов: они всегда сохраняют одно и то же значение 1rem = 1em = размер шрифта, установленный браузером. Причина такого поведения объясняется в спецификации медиа-запроса :

Относительные единицы в медиазапросах основаны на начальном значении, что означает, что единицы никогда не основаны на результатах объявлений. Например, в HTML единица em относится к начальному значению размера шрифта, определяемого uesr-agent или пользовательскими настройками, а не каким-либо стилем на странице.

Взгляните на пример:

See the Pen Using rem Units with Media Query Breakpoints by SitePoint (@SitePoint) on CodePen.light

Во-первых, в нашем HTML у нас есть элемент <span>, в который мы напишем ширину области просмотра:

Document width: <span></span>px

Далее у нас есть два медиазапроса, один с блоками rem, а другой с em (для простоты используется Sass):

html {
font-size: 62.5%; /* 62.5% of 16px = 10px */

@media (min-width: 20rem) {
/* 20*16px = 320px */
background-color: lemonchiffon;
font-size: 200%;
/* 200% of 16px = 32px */
}

@media (min-width: 30em) {
/* 30*16px = 480px */
background-color: lightblue;
font-size: 300%; /* 300% of 16px = 48px */
}
}

Наконец, мы используем немного jQuery для отображения ширины области просмотра на странице, обновляя значение при изменении размера окна:

$('span').text($(window).width());

$(window).on('resize', function(e) {
$('span').text($(window).width());
});

Мы начнем с трюка с 62,5%, чтобы показать, что измененный размер корневого шрифта не влияет на значения, используемые для медиазапросов. Изменяя ширину окна браузера, мы можем видеть, что первый медиа-запрос начинает работать с 320px (20 × 16px), а второй становится активным с 480px (30 × 16px). Ни одно из объявленных нами изменений размера шрифта не повлияло на точки останова. Единственный способ изменить значения точки останова медиазапроса – изменить размер шрифта по умолчанию в настройках браузера.

По этой причине не имеет значения, используем ли мы единицы em или rem для точек останова медиазапроса. Zurb Foundation (в настоящее время v6.5.3 на момент написания этой статьи) использует единицы em в медиазапросах.

В поисках доступности

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

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

Использование rem для масштабирования документов

Третье применение, которое мы можем найти для блоков rem, – создание масштабируемых компонентов. Выражая ширину, поля и отступ в единицах rem, становится возможным создать интерфейс, который увеличивается или уменьшается в соответствии с размером корневого шрифта. Давайте посмотрим, как это работает, на нескольких примерах.

Пример первый:

See the Pen Sizing Modules with Rem Units in Breakpoints by SitePoint (@SitePoint) on CodePen.light

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

Давайте посмотрим на другой:

See the Pen Dynamic Sizing of Modules with Rem Units by SitePoint (@SitePoint) on CodePen.light

Во втором примере мы делаем то же самое изменение, используя JavaScript. На этот раз пользователь может контролировать размер интерфейса, подстраивая его под свои нужды. Добавьте способ хранения этих пользовательских значений (используя базу данных, файлы cookie или локальное хранилище), и вы получите базу системы персонализации, основанную на предпочтениях пользователя.

Вывод

На этом мы заканчиваем нашу встречу с модулями CSS rem. Очевидно, что использование этих модулей в нашем коде дает много преимуществ, таких как скорость отклика, масштабируемость, улучшенный опыт чтения и большая гибкость в определении компонентов. Устройства Rem не являются универсальным решением «серебряной пули», но при тщательном развертывании они могут решить многие проблемы, которые раздражали разработчиков в течение многих лет. Каждый из нас должен раскрыть весь потенциал ремов. Запустите свои редакторы, экспериментируйте и делитесь своими результатами с остальными.