Использование viewport-единиц в типографике

Недавно натолкнулся на статью Zell Liew «Viewport Unit Based Typography». Она показалась мне очень интересной, поэтому решил перевести, по мере своих возможностей, и выложить её у себя.

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

Второй момент: предыдущую статью про rem и em не перевожу, поэтому начальное лирическое отступление пропускаю. Итак, поехали…

Что такое viewport-юниты?

Есть четыре разных viewport-юнитов на сегодня:

  • vw — процент от ширины вьюпорта
  • vh — процент от высоты вьюпорта
  • vmax — наибольшее значение из vw и vh
  • vmin — наименьшее значение из vw и vh

В данном случае, под вьюпортом подразумевается окно браузера. То есть 1vw — это 1% от ширины окна. 100vw, соответственно, — полная ширина окна.

100vw и 100vh
100vw и 100vh

Плюс viewport-юнитов заключается в том, что они автоматически пересчитываются при изменении окна браузера. Это происходит при загрузке, при изменении размера окна или при смене ориентации устройства.

Итак, если viewport-юниты автоматически пересчитываются, то это даёт нам возможность легко создать элемент, который всегда занимает четверть от размера окна.

Элемент всегда занимает четверть размера окна
Элемент всегда занимает четверть размера окна

Итак, это был раздел «viewport для чайников». А теперь вперёд, к самой мякотке!

Использование viewport-единиц для адаптивной типографики

Есть одна причина из-за которой вы должны подумать о том, чтобы использовать viewport-юниты в типографике: они автоматически пересчитываются в зависимости от размера окна браузера пользователя. Это означает, что вам не нужно менять размеры шрифта в медиа-запросах.

Давайте рассмотрим пример, чтобы понять о чём идёт речь.

Рассмотрим код, в котором мы меняем размер шрифта с 16px на 20px, при достижении размером окна 800px:

В коде вы видите, что размер шрифта прыгает с 16px до 20px, когда размер окна становится больше 800px. Так мы делали долгое время и это нормально.

Иногда приходится добавлять ещё один промежуточный медиа-запрос, чтобы указывать какое-то среднее значение размера шрифта, при котором всё будет отображаться нормально:

Обычно, мы ограничиваемся тремя-четырьмя промежуточными медиа-запросами. Можно использовать больше, но это уже будет перебор.

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

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

Посмотрим на следующий код:

Размер шрифта изменяется автоматически
Размер шрифта изменяется автоматически

Круто, да?

Но проблема в том, что viewport-единицы слишком чувствительны к изменению размера окна.

Если вы укажете размер шрифта 3vw, как в примере выше, то получите размер шрифта в 10px на экране шириной в 320px (мобильные) и  43px на экране шириной в 1440px (ноутбук). Это слишком маленькое и слишком большое значение.

Теперь перед нами стоит интересная задача — укрощение вьюпорта.

К счастью, есть простой способ решения данной проблемы: мы установим минимальное значение размера шрифта и будем его увеличивать с помощью небольшого viewport-значения, используя calc().

Вот как это выглядит:

Круто, не так ли? Я узнал об этом способе от Mike Riethmuller в его статье «Precise control over responsive typography».

К сожалению, я понял, что этот код не работает в некоторых браузерах. Например, это не работает на Safari для Mac.

Исправление, на удивление, просто. Мы совмещаем использование процентов и vw и это позволяет данному коду работать в Safari:

Тадам!

Зверь укрощён!
Зверь укрощён!

Отлично! Теперь мы реально можем перестать использовать em-ы, rem-ы и медиа-запросы? Я не могу дождаться момента, когда попробую это!

Следующая проблема, которую я должен был решить, — указание в viewport-единицах размеров заголовков (h1-h6).

Установка размера других элементов типографики в viewport-единицах

Первое что я попробовал — это создание заголовка h1, который в два раза больше основного шрифта. Оказалось, что не всё так просто 🙁

Я просто взял значение, указанное в font-size для html, и умножил его на два. Но получилось, что размер заголовка стал больше, чем он должен был быть:

Размер заголовка неправильный :(
Размер заголовка неправильный 🙁

Это случилось потому что я использовал font-size для h1 основанный на процентах. То есть, я пересчитал font-size для h1, после того, как он унаследовал уже пересчитанный размер у html.

Давайте рассмотрим это на примере и, для удобства, используем другие числа. Представим, что мы сейчас размер нашего окна составляет 800px , а значение шрифта — 16px.

  • Сначала вычисляется значение font-size для html: 112.5% от 16px = 18px (112.5/100 * 16px)
  • Затем вычисляется значение, указанное в vw: 800px * 0.25 ÷ 100 = 2px
  • И, наконец, значения складываются: 18px + 2px = 20px

Пока всё идёт хорошо. Отлично!

Мы будем использовать тот же метод для вычисления размера h1. Обратите особое внимание на значение 112.5% в вычислении.

  • 112.5% для h1 превращается в 22.5px (112.5/100 * 20px)
  • 0.25vw, всё также, равно 2px (800px * 0.25 ÷ 100)
  • В итоге получаем 49px ((22.5px + 2px) * 2)

Значение h1 должно было быть равным 40px, так как оно должно быть в два раза больше основного текста. А 49px не равно 40px 🙁

Проблема вызвана наследование значения font-size для h1 от html. Есть два решения этой проблемы.

Первое: просто заменить 112.5% на 100% для h1:

Второе: убедитесь, что размер шрифта не наследуется элементами.

Оба способа не очень хороши и меня это не устраивало.

В итоге, я решил, что лучший способ — использование rem и em. Не стоит забывать о старых друзьях, когда появились новые 🙂

Теперь размер заголовка правильный!
Теперь размер заголовка правильный!

Так как мы говорим об изменении размера шрифта, следующий вопрос, который мы зададим себе, будет «А что там с межстрочными интервалами?».

Ну что ж, давайте теперь поговорим об этом.

Межстрочные интервалы при использовании viewport-юнитов

Ответ прост. Вы заметили, что viewport-юниты используются только для установки значения для корневого элемента (html)? Во всех остальных случаях мы всё ещё используем rem-ы и em-ы! Это означает, что вы можете использовать rem-ы и em-ы так, как я описывал в статье «Everything I know about Responsive Web Typography». Ничего не изменилось! 🙂

Чуть не забыл! Ещё одна вещь, о которой стоит сказать до того, как мы закончим статью.

Была ещё одна проблема, которую мне пришлось решить: «Как рассчитать так, чтобы размер шрифта был 20px при достижении окном размера 800px?». Вопрос можно сократить до одного слова — «Точность». Проще говоря, как я могу быть точно уверен, что размер шрифта станет таким, каким надо, при увеличении окна до 800px?

Точность

Оказывается, Майк решил эту проблему. Давайте просто возьмём его формулу и разберём её.

Итак, что мы хотим:

  • При viewporte в 600px font-size равен 18px
  • При viewporte в 1000px font-size равен 22px

Первое что мы делаем — преобразуем меньшее значение (18px) в проценты: 18/16 * 100% = 112.5%.

Следующее: мы вычисляем количество vw. Здесь чуть сложнее.

Для этого мы возьмем разницу между font-size (22px — 18px), поделим на разницу viewport-а (1000 — 600) и умножим на 100vw — меньшее значение viewport-а (100vw — 600px).

Вот как это выглядит:

Это может показаться немного сложным, но как только вы поймете из чего он состоит, то сможете упростить его в SASS-миксин.

Indrek Paas уже сделал это здесь.

Супер точность

А что делать, если вы хотите, чтобы шрифт увеличивался с разной скоростью в разных промежутках?

Вот один из ответов:

Но в реальности вы, скорее всего, не будете увеличивать шрифт с разной скоростью.

Поэтому более реалистичным будет следующий код:

Всё, парни, закругляемся!

И, под конец, главный вопрос: «Я могу это всё использовать на реальных проектах?»

Возможно. Я работал с viewport-юнитами достаточное время, чтобы сделать какой-то вывод. Прежде чем пускать это всё в продакшен нужно:

  • Сделать SASS-миксин
  • Протестировать в разных браузерах на наличие каких-нибудь багов

Будет круто, если вы нашли какие-то ошибки и сообщите о них в комментариях.

Послесловие

Итак, мы поговорили об использовании viewport-единиц для указания размера шрифтов. Viewport-единицы могут быть очень полезны, так как они автоматически пересчитываются при изменении размера окна.

В ходе реализации, я заметил, что лучше всего их использовать только для html. Для всего остального есть MasterCard лучше использовать rem-ы и em-ы.

А что вы думаете об использовании viewport-единиц? Буду рад услышать ваше мнение в комментариях!


Послесловие переводчика:

Как я уже и говорил, мне статья очень понравилась. По ходу перевода были некоторые сложности, в частности, например, с переводом термина «vertical rhythm».

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

P.S. Блин, этот смайлик реально крутой! (╯°□°)╯︵ ┻━┻

UPDATE 21.11.2016

Если размер шрифта по данной формуле указан и у родителя, и у дочернего элемента, то дочерний элемент высчитывает процент от родительского и устанавливает его неправильно.

Чтоб избежать данной проблемы нужно заменить проценты на rem-ы (чтоб размер высчитывался не относительно родителя, а относительно корневого элемента). То есть, если размер шрифта стоит по умолчанию (16px), а размер какого-то блока нужен, например, 24px, то в формуле указываем не 150%, а 1.5rem.

comments powered by HyperComments

Автор

webbeaver

webbeaver

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

Дайджест интересных материалов из мира веб-разработки и IT за последнюю неделю №204 (21 — 27 марта 2016) - itfm.pro
2016-03-27 22:10:11
[…] Использование viewport-единиц в типографике […]