Единицы измерения области просмотра используются вот уже несколько лет. Они практически полностью поддерживаются основными браузерами. Тем не менее я продолжаю находить новые и любопытные способы их применения. Я подумала, что было бы здорово сначала вспомнить базовые вещи, а затем затронуть некоторые из моих любимых вариантов использования этих единиц.



Что такое единицы измерения области просмотра?


Между 2011 и 2015 годами в спецификациях CSS, разработанных W3C, в 3-ем уровне модуля Значения и единицы CSS, появились четыре новые единицы, которые связаны непосредственно
с параметрами области просмотра. Новые единицы — vw, vh, vmin, и vmax — работают аналогично существующим единицам длины, таким как px или em, но представляют собой процентные величины от текущей области просмотра браузера.


  • Viewport Width (vw) – это процентная величина от общей ширины области просмотра. 10vw представляет собой 10% от текущей ширины области просмотра, скажем, 48px на телефоне с экраном шириной 480px. Разница между % и vw наиболее сопоставима с отличием между единицами em и rem. Длина в % рассчитывается относительно ширины текущего контекста (контейнера), а длина vw — относительно общей ширины области просмотра браузера.

  • Viewport Height (vh) — это процентная величина от общей высоты области просмотра. 10vh составляет 10% от текущей высоты области просмотра.

  • Viewport Minimum (vmin) — это процентная величина от ширины или высоты области просмотра, в зависимости от того, которая из двух меньше. 10vmin соответствует 10% от текущей ширины области просмотра в книжной ориентации и 10% от высоты области просмотра в альбомной ориентации.

  • Viewport Maximum (vmax) — это процентная величина от ширины или высоты области просмотра, в зависимости от того, которая из двух больше. 10vmin будет равняться 10% от текущей высоты области просмотра в книжной ориентации и 10% ширины области просмотра в альбомной ориентации. К сожалению и как бы странно это ни звучало, единица vmax еще не поддерживается браузерами Internet Explorer и Edge.

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


Отзывчивая типографика


Стало популярным использовать единицы измерения области просмотра в отзывчивой типографике — настраивать размер шрифта таким образом, чтобы он увеличивался и уменьшался в зависимости от текущего размера области просмотра. Использование единиц измерения области просмотра для определения размера шрифта имеет интересный (опасный) эффект. Как вы видите, шрифты масштабируются очень быстро — от нечитабельно-мелкого до крайне крупного размера в очень малом диапазоне.


html {
font-size: 3vw;
margin: .5em;
}

h1 {
font-size: 4vmax;
}

h2 {
font-size: 4vmin;
}

h1, h2 {
font-weight: bold;
}

h1, h2, p {
margin: .5em 0;
}


Такое резкое масштабирование явно не подходит для повседневного использования. Нам нужно что-то более тонкое — минимальные и максимальные значения. Также нужно больше контроля над диапазонами увеличения показателя. Тут нам поможет функция calc(). Для определения базового размера шрифта мы можем использовать более стабильные единицы (скажем, 16px). Мы также можем уменьшить диапазон подстраивания значения под размер области просмотра (0.5vw). Таким образом, браузер будет выполнять следующие математические вычисления: calc(16px + 0.5vw)



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


body {
  // размер шрифта увеличивается на 1px через каждые 100px ширины области просмотра
  font-size: calc(16px + 1vw);
  // междустрочный интервал увеличивается вместе со шрифтом
  // и получает дополнительный прирост на 0.1em + 0.5px через каждые 100px ширины области просмотра
  line-height: calc(1.1em + 0.5vw);
}

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


h1 {
  font-size: calc(1.2em + 3vw);
}

@media (min-width: 50em) {
  h1 {
    font-size: 50px;
  }
}

Тут я поняла, что было бы здорово, если бы существовало такое свойство, как max-font-size.


Наши коллеги разработали более сложные расчеты и миксины Sass для определения точных диапазонов масштабирования размера текста через конкретные медиа-запросы. Есть несколько статей на CSS Tricks, в которых объясняется этот метод. Там же представлены фрагменты кода, которые помогут попробовать его в деле.





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


Полноэкранные блоки, hero images и прилипающие футеры


Существует великое множество вариаций вёрстки во всю высоту окна (или подразумевающей ограничение по высоте) — от интерфейсов в стиле рабочего стола до hero images, широких макетов и прилипающих футеров. Единицы измерения области просмотра помогут вам со всем перечисленным.


В интерфейсе в полную высоту в стиле рабочего стола страница часто разбивается на разделы, которые скроллятся по отдельности. Такие элементы, как хедер, футер, боковые панели, остаются на месте при любом размере окна. Сегодня это обычная практика для многих веб-приложений, а единицы vh делают реализацию такого интерфейса гораздо проще. Ниже приведен пример с использованием нового синтаксиса CSS Grid:



Одно правило для body — height: 100vh — задает высоту вашему приложению равной высоте области просмотра. Убедитесь, что для элементов внутри body заданы значения overflow, чтобы их содержимое не обрезалось. Такой же вёрстки можно добиться, используя flexbox или плавающие элементы. Заметьте, что с вёрсткой в полную высоту в некоторых мобильных браузерах могут возникать проблемы. Есть хороший фикс для Safari на iOS, который мы используем для наиболее часто встречающихся нестандартных случаев.


Прилипающие футеры можно создать аналогичным образом. Все, что нужно — правило для body height: 100vh заменить на min-height: 100vh, и футер будет зафиксирован внизу экрана, до тех пор пока не сместится контентом вниз.



Используйте единицы vh для определения свойств height, min-height или max-height различных элементов и создавайте полноэкранные разделы, hero images и многое другое. В новом редизайне OddBird мы ограничили высоту hero images правилом max-height: 55vh, чтобы они не вытесняли заголовки со страницы. На моем собственном сайте я использовала правило max-height: 85vh, чтобы больше выделить изображения. На других сайтах я применила минимальную высоту — min-height: 90vh — к разделам.


Этот пример демонстрирует сразу и hero image котика, ограниченное максимальной высотой, и раздел с минимальной высотой. Используя все эти приемы, вы можете максимально управлять тем, как контент будет заполнять окно браузера и реагировать на различные размеры области просмотра.


Соотношение ширины и высоты для резиновой вёрстки


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


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


/* во всю ширину * соотношение высоты и ширины */
.full-width {
  width: 100vw;
  height: calc(100vw * (9/16));
}

Такие расчеты не обязательно выполнять именно в браузере с поддержкой функции calc. Если вы используете препроцессор, как, например, Sass, того же эффекта можно добиться с помощью подобного расчета: height: 100vw * (9/16). Если вам нужно ограничить максимальную ширину, вы также можете ограничить максимальную высоту:


/* максимальная ширина * соотношение высоты и ширины */
.full-width {
  width: 100vw;
  max-width: 30em;
  height: calc(100vw * (9/16));
  max-height: calc(30em * (9/16));
}

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



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


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



«Разрывая» контейнер


Уже многие годы мы используем текстовые блоки ограниченного размера на пару с фонами на всю ширину. В зависимости от разметки или CMS, здесь могут возникать проблемы. Как уйти от необходимости ограничивать содержимое размером контейнера, но обеспечить при этом точно такое же заполнение им окна браузера?


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


.full-width {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

Есть более подробные статьи, посвященные данной технике, как на Cloud Four, так и здесь, на CSS Tricks.


Креативные реализации


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



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


Оригинальная статья: Fun with Viewport Units by Miriam Suzanne
Поделиться с друзьями
-->

Комментарии (11)


  1. bro-dev
    19.06.2017 17:18

    Для меня как пользователя это неприятное и неожиданное поведение когда зум в браузере не работает. Имхо нужно абсолютно все размеры давать в пикселях, а пользователь уже сам если хочет крупнее то увеличит как ему удобно. Контейнеры само собой резиново и адаптивно.


  1. dom1n1k
    19.06.2017 17:49
    +3

    В статье не хватает одного «нюанса», с которого нужно начинать любой разговор о единицах вьюпорта и выделять красным цветом — единицы vw/vh отсчитываются от размеров вьюпорта включая ширину полос прокрутки.
    Это обстоятельство для многих (как и для меня в своё время) становится большим сюрпризом и рушит много логичных идей использования таких многообещающих единиц. Нужно понимать, что 100vw != 100%. На самом деле в большинстве случаев 100vw > 100% и причем соотношение между ними не постоянно, а зависит от ОС и её настроек!

    Так написано в спецификации. Конечно, авторы спецификации тоже не дураки, и у них были на то свои причины. Но рядовому верстальщику от этого не легче — эта неприятная особенность изрядно девальвирует ценность единиц вьюпорта.

    Ну и идея завязывать на vw интерлиньяж — мягко говоря, сомнительна.


    1. nullc0de
      20.06.2017 05:50
      -1

      Они зато просчитываются быстрее и шаблон быстрее рендерится чем со 100%, они нельзя называются единицами видимой области. Процентные единицы требует просчет родителя контейнера, что на сложных шаблонах с большим dom деревом замедляет отрисовку, по это же причине верстка флоатами с процентами медленее flex. На крупных ресурсах % могут замедлить довольно значительно отрисовку, особенно если это SPA и при взаоимодействии пользователя с интерфейсом могут возникнуть тормоза.
      Мой плагин например все необходимые расчеты с calc делает автоматически, и дизайн адаптивный, засчет использования языка макросов


  1. anmiles
    19.06.2017 23:06

    Кажется «независимо от» следует заменить на «в зависимости от».


    1. gprokofyeva
      19.06.2017 23:22

      Спасибо. Поправлено.


  1. jankovsky
    20.06.2017 10:22
    -2

    Старо как мир. И не хочу Вас огорчать, но давно известно, что ни vw, ни vh, ни flexbox и все остальное перечисленное в статье в будущую спецификацию не войдет.


    1. pepelsbey
      20.06.2017 11:00

      Что это вообще значит в будущую спецификацию не войдет? Они уже в спецификациях и широко поддерживаются браузерами.


    1. gprokofyeva
      20.06.2017 12:12

      Можно ссылку на источник, откуда взята такая инфа?
      По ссылке рабочий черновик будущей спецификации https://drafts.csswg.org/css-values-3/#viewport-relative-lengths
      Пока содержит viewport-единицы.


      1. SelenIT3
        20.06.2017 20:02

        Возможно, в n-ном пересказе так причудливо исказилась информация, что CSS как язык ушел от понятия версий и не будет «CSS4», «CSS5» и т.д. (хотя отдельные модули, составляющие один большой язык CSS, бывают и 4-го, а с недавних пор и 5-го уровня). А что касается модуля значений и единиц, то он не просто есть, но уже дошел до статуса кандидата в рекомендации (т.е. полностью готов теоретически и реализован независимо и единообразно как минимум в двух браузерах — в переводе с W3C-шного на человеческий:) и входит в официальное определение CSS 2017-го года.


  1. pepelsbey
    20.06.2017 11:06

    Не бойтесь слова вьюпорт. Представьте, что вы кричите коллеге в другом конце комнаты:


    Какой размер шрифта ставить: полторы единицы изменения области просмотра или больше?

    Нет конечно, скажете полтора вьюпорта и всё. Так зачем в статье усложнять?


    1. gprokofyeva
      20.06.2017 12:20

      Все верно, в устной речи, да и в любом обсуждении, я не стала бы использовать такие длинные термины.
      Но в переводе все-таки предпочитаю использовать именно переводы терминов, как «поля», а не «маргины», «отступы», а не «паддинги» и т.д. Мне трудно представить книгу, в которой бы было написано что-то вроде «Что такое единицы вьюпорта?»