Какие единицы использовать для медиа-запросов: px, em или rem?

Итак, очередной вольный перевод статьи Zell Liew под названием «PX, EM or REM Media Queries?».  Все примечания автора и его плоские шуточки окрашены в светлый цвет, дабы не мозолить глаза. Погнали!

Вы когда-нибудь задумывались о том, какие единицы использовать в медиа-запросах: px, em или rem? Я вот задумывался и теперь решил выяснить, что же использовать.

Когда я создавал библиотеку mappy-breakpoints, чуть больше года назад, я использовал rem-ы. Затем, после разговора с Sam Richard, я переключился на em, потому что узнал, что особой разницы между ними нет. Нахрена переключился тогда?

Кроме em и rem, популярным методом является указание медиа-запросов в старых добрых пикселях. Я задался вопросом, можно ли использовать пиксели в медиа-запросах пока разработчики браузеров не решили проблему с масштабированием.

И на этой неделе я решил поставить точку в этом вопросе.

Чтение этой статьи подразумевает то, что вы знакомы с em и rem. Если нет — валите на хрен вам сначала сюда.

Основной эксперимент

Я создал три div-а, один для пикселей, один для em-ов и один для rem-ов и окрасил их в разные цвета, чтобы легко различать их.

.pixel { background: red; }
.em { background: green; }
.rem { background: blue; }

Затем создал медиа-запрос с min-width для всех трёх блоков, использовав соответствующие единицы. И, чтобы сразу увидеть разницу, сделал их полупрозрачными. Вот как выглядит код для пикселей:

.pixel {
  background: red;  
  @media (min-width: 400px) {
    opacity: 0.5
  }
}

Следующий шаг — выяснить, как это сделать для em и rem.

В этом эксперименте я хотел выяснить, будет ли разница, если условия идеальны. Другими словами, ничего из следующего списка не произошло:

  • Font-size для html изменён.
  • Пользователь масштабировал страницу/
  • Пользователь изменил размер шрифта браузера.

Так как условия идеальны, я смело могу заявить, что 16px == 1em == 1rem. Значит 400px == 25em == 25rem.

.pixel {
  background: red;  
  @media (min-width: 400px) {
    opacity: 0.5
  }
}

.em {
  background: green;  
  // 400 ÷ 16 = 25
  @media (min-width: 25em) {
    opacity: 0.5
  }
}

.rem {
  background: blue;  
  // 400 ÷ 16 = 25
  @media (min-width: 25rem) {
    opacity: 0.5
  }
}

Если все медиа-запросы верны, мы должны увидеть, как они подействуют на 400px.

Так оно и есть (проверял на всех браузерах).

Основной эксперимент.
Основной эксперимент.

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

После того, как всё прошло удачно, попробуем провести эксперимент в не совсем идеальных условиях. Итак, ещё раз перечислим сценарии:

  • Font-size для html изменён.
  • Пользователь масштабировал страницу/
  • Пользователь изменил размер шрифта браузера.

Давайте рассмотрим их по-одному.

1. Размер шрифта html изменён

Первый сценарий — обычное дело.Ведь почти все сайты меняют размер шрифта в CSS:

html { 
  // изменение размера шрифта по-умолчанию 
  font-size: 200% 
}

Итак, я изменил размер шрифта на 200%, а это значит, что 1em и 1rem теперь равен 32px. А если это изменение влияет на em и rem, значит медиа-запросы должны срабатывать на 800px.

Результат в Chrome, Firefox и IE11.
Результат в Chrome, Firefox и IE11.

Это правильное поведение. Em и rem не должны зависеть от изменений размера шрифта html, потому что они основаны на внутреннем размере шрифта браузера.

К сожалению, в Safari что-то пошло не так. Rem-запрос включается только на 800px 🙁

Результат в Safari.
Результат в Safari.

Так как это происходило только в Safari, мне стало интересно: происходит ли тоже самое на мобильной версии браузера. Оказывается, да.

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

2. Пользователь масштабировал страницу

Следующий сценарий тоже довольно распространён. Если текст на сайте маленький, пользователь может увеличить его, используя zoom браузера.

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

Масштабирование страницы пользователем.
Масштабирование страницы пользователем.

Результаты экспериментов в Chrome, Firefox и IE показал такие же результаты. Медиа-запросы в пикселях срабатывают в то же время, что и запросы в em и rem.

Результат в Chrome, Firefox и IE11.
Результат в Chrome, Firefox и IE11.

И, как вы уже догадались, Safari не может в zoom 🙁

Результат в Safari.
Результат в Safari.

К сожалению, это значит, что мы не можем использовать пиксели в медиа-запросах. Safari не поддерживает их должным образом (или вы решили забить на Safari?).

Переходим к последнему эксперименту, может там что-то интересное произойдёт?

3. Пользователь изменил размер шрифта браузера по-умолчанию

Многие разработчики надеются, что пользователь ничего не менял, потому что хрен поймешь, где там что меняется.

Это было бы круто, ведь нам не нужно было бы проделывать третий эксперимент! 🙂

К сожалению, мы не можем гарантировать этого и наш долг, как разработчиков, сделать, чтобы всё было нормально.

В этом эксперименте я увеличил размер шрифта браузера по-умолчанию. Если хотите сделать тоже самое — вот путь настроек:

  • Chrome: настройки > показать дополнительные настройки > вид страницы.
  • Firefox: настройки > содержимое > шрифты и цвета.
  • IE: страница > размер шрифта. В IE11 что-то не нашёл такого.

Единственный браузер, в котором я не нашёл данную функцию, оказался ВНЕЗАПНО Safari. Я только сделал, чтобы наименьший размер шрифта был больше 16px (настройки > дополнительные настройки > доступность (?)).

Это оказался единственным экспериментов, где результаты у всех браузеров были одинаковыми.

Результаты всех браузеров в третьем эксперименте.
Результаты всех браузеров в третьем эксперименте.

Как вы видите, медиа-запросы в пикселях срабатывают раньше, чем в em и rem.

Это не баг. Всё правильно, ведь пиксели — абсолютные единицы. Медиа-запрос срабатывает на 400px и не важно, что пользователь изменил размер шрифта по-умолчанию.

А вот em и rem основаны на размере шрифта браузера. Следовательно, они меняются, когда пользователь меняет размер шрифта браузера.

Что ж… Жаль, что приходится вас расстраивать, любители пикселей, но пиксель не подходит для задания медиа-запросов. 😱😱😱

Завершающий эксперимент

Как вы увидели в экспериментах выше, только em нормально работает во всех браузерах. Нет никакой разницы между em и rem, не считая бага в Safari.

Пиксели показали хорошие результаты в двух из трёх экспериментов (опять же, за исключением Safari). К сожалению, третий эксперимент они провалили, а это значит, что вы не можете их использовать, если хотите чтобы у пользователей, изменивших стандартный размер шрифта в браузере, всё отображалось нормально.

Таким образом, мой совет — используйте em-ы в медиазапросах.

Если вы используете какую-либо библиотеку, медиа-запросы которой основаны не на em-ах — скиньте разработчику ссылку на эту статью, чтобы он знал о последствиях. Или не стесняйтесь и переходите на em-основанные библиотеки вроде Mappy-breakpoints, Breakpoint-sass или sass-mq.

comments powered by HyperComments

Автор

webbeaver

webbeaver

Верстаю, читаю, учусь