От автора: единицы измерения CSS, связанные с областью просмотра, появились несколько лет назад, и со временем я вижу, что они все больше используются разработчиками. Их преимущество заключается в том, что мы можем гибко и динамично оценивать размер вещей без необходимости использования JavaScript. Кроме того, для них легко предоставить запасной вариант.
В этой статье мы узнаем о единицах измерения CSS, связанных с областью просмотра, и о том, как их применять, а также рассмотрим некоторые варианты использования и решения общих проблем. Давайте начнем!
В соответствии со спецификацией CSS, проценты в единицах измерения, связанных с областью просмотра, относятся к размеру исходного содержащего блока, который является корневым элементом веб-страницы. К ним относятся: vw, vh, vmin, и vmax.
Ширина области просмотра
Единица измерения vw представляет собой процент ширины корневого элемента. Один vw равен 1% ширины области просмотра.
У нас есть элемент со следующим CSS:
.element { width: 50vw; }
Когда ширина области просмотра равна 500px, 50vw будет рассчитываться, как показано ниже:
width = 500*50% = 250px
Высота области просмотра
Единица измерения vh представляет собой процент от высоты корневого элемента. Один vh равен 1% высоты области просмотра.
У нас есть элемент со следующим CSS:
.element { height: 50vh; }
Когда высота области просмотра равна 290px, 70vh будет рассчитываться, как показано ниже:
height = 290*70% = 202px
Вот и все. Давайте перейдем к другому виду единиц, связанных с областью просмотра!
Единица измерения Vmin
vmin представляет значение минимальной ширины и высоты области просмотра. Если ширина области просмотра больше его высоты, то значение будет рассчитываться на основе высоты. Давайте возьмем следующий пример.
У нас есть смартфон в альбомной ориентации, и для элемента задана vmin. В этом случае значение будет рассчитываться на основе высоты области просмотра, поскольку она меньше ширины.
.element { padding-top: 10vmin; padding-bottom: 10vmin; }
Вот как будет рассчитываться vmin:
Как вы уже догадались, результат будет рассчитан следующим образом:
padding-top = (10% of height) = 10% * 164 = 16.4px padding-bottom = (10% of height) = 10% * 164 = 16.4px
Единица измерения Vmax
Это противоположность vmin. Значение рассчитывается на основе максимальной ширины и высоты.
Давайте рассмотрим следующий пример.
.element { padding-top: 10vmax; padding-bottom: 10vmax; }
Результат будет рассчитан как:
padding-top = (10% of width) = 10% * 350 = 35px padding-bottom = (10% of width) = 10% * 350 = px
Чем единицы измерения, связанные с областью просмотра, отличаются от процентов?
Единицы измерения, связанные с областью просмотра, зависят от корневого элемента страницы, а проценты зависят от контейнера, в котором они находятся. По этой причине они отличаются друг от друга, и у каждого есть свои варианты использования.
Варианты использования для единиц измерения, связанных с областью просмотра
В следующих разделах я расскажу о некоторых случаях применения единиц измерения, связанных с областью просмотра, и о том, как их реализовать в проектах.
Размер шрифта
Единицы измерения, связанные с областью просмотра, идеально подходят для адаптивной типографики. Например, мы можем использовать следующее для заголовка статьи:
.title { font-size: 5vw; }
font-size заголовка будет увеличиваться или уменьшаться в зависимости от ширины области просмотра. Это как задать размер шрифта 5% от ширины области просмотра. Тем не менее, может быть заманчиво просто использовать его без надлежащего тестирования.
Обратите внимание на то, что размер шрифта стал очень малым для мобильных устройств, это плохо сказывается на доступности и удобстве использования. Насколько я знаю, минимальный размер шрифта на мобильном устройстве не должен выходить за рамки 14px. В GIF размер шрифта уменьшился ниже 10px.
Чтобы решить эту проблему, мы должны задать для заголовка минимальный размер шрифта. CSS calc() вам в помощь!
.title { font-size: calc(14px + 2vw); }
Функция CSS calc() будет иметь базовое значение 14px, и добавит к нему 2vw. Учитывая это, значение размера шрифта не станет слишком маленьким.
Еще одна важная вещь, которую следует учитывать — это как будет вести себя размер шрифта на больших экранах, например, на 27-дюймовом iMac. Что случится? Ну, вы уже догадались. Размер шрифта увеличился до 95px, что слишком много. Чтобы предотвратить это, мы должны использовать медиа-запросы и изменять font-size в определенных контрольных точках.
@media (min-width: 1800px) { .title { font-size: 40px; } }
Сбрасывая font-size, мы можем быть уверены, что размер не будет слишком большим. Вам также может понадобиться добавить несколько медиа-запросов, но это зависит от вас и от контекста проекта.
Разделы на весь экран
Иногда нам нужен раздел, который должен охватывать 100% высоты области просмотра. Их еще называют «полноэкранными разделами». Для этого мы можем использовать высоту окна просмотра.
.section { height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; }
Указывая height: 100vh, мы можем гарантировать, что высота раздела будет 100% от области просмотра. Также я добавил несколько flexbox для центрирования контента по горизонтали и вертикали.
Липкий футер
На большом экране вы можете заметить, что содержимое сайта слишком короткое, а футер не прилегает к нижней части экрана. Это нормально, и это не считается плохой практикой. Тем не менее, это можно улучшить. Рассмотрим следующий случай:
Чтобы решить это, нам нужно задать для основного контента высоту, равную высоте области просмотра — (хэдер и футер). Сделать это динамически довольно сложно, но с помощью единиц измерения CSS, связанных с областью просмотра, это делается так.
1. Первое решение: calc и единицы, связанные с областью просмотра
Если высота хэдера и футера фиксирована, можно объединить обе функции calc() с единицами, связанными областью просмотра. Вот как:
header, footer { height: 70px; } main { height: calc(100vh - 70px - 70px); }
Это решение не всегда работает, особенно для футера. В своей работе я не использовал футер с фиксированной высотой, потому что это невозможно, например, на экранах разных размеров.
2. Второе решение: Flexbox и единицы, связанные с областью просмотра (рекомендуется )
Добавив для элемента body высоту 100vh, мы можем использовать flexbox, чтобы основной элемент занял оставшееся пространство.
body { min-height: 100vh; display: flex flex-direction: column; { main { /* This will make the main element take the remaining space dynamically */ flex-grow: 1; }
Проблема решена, и у нас есть липкий футер независимо от длины контента.
Адаптивные элементы
Я наткнулся на эту статью во время исследования, и она мне действительно понравилась, поэтому я возьму из нее пример использования и объясню его по-своему.
Предположим, у нас есть порт-фолио для демонстрации наших адаптивных дизайнерских работ, и у нас есть три устройства (мобильное, планшетное и портативное). Каждый макет содержит изображение. Цель состоит в том, чтобы сделать их на 100% адаптивными в CSS.
Используя сетку CSS и единицы измерения, связанные с областью просмотра, мы можем сделать это полностью адаптивным и динамичным.
<div class="wrapper"> <div class="device laptop"></div> <div class="device mobile"></div> <div class="device tablet"></div> </div>
Обратите внимание, что в grid-* свойствах используются единицы измерения, связанные с областью просмотра. Они также используются для border, border-radius и других свойств. Все это дает оптимальный результат.
.wrapper { display: grid; grid-template-columns: repeat(20, 5vw); grid-auto-rows: 6vw; } .mobile { position: relative; z-index: 1; grid-column: 2 / span 3; grid-row: 3 / span 5; } .tablet { position: relative; z-index: 1; grid-column: 13 / span 7; grid-row: 4 / span 4; border-bottom: 1vw solid #a9B9dd; border-right: solid 3vw #a9B9dd; } .laptop { position: relative; grid-column: 3/span 13; grid-row: 2 / span 8; } /* Viewport units are used for the bottom, left, right, height, and border-radius. Isn't that cool? */ .laptop:after { content:""; position:absolute; bottom: -3vw; left: -5.5vw; right: -5.5vw; height: 3vw; background-color: #a9B9dd; border-radius: 0 0 1vw 1vw; }
Выход за пределы контейнера
Я нашел один вариант использования, который наиболее подходит для редакционных макетов. Дочерний элемент, который занимает 100% ширины области просмотра, даже если ширина его родителя ограничена. Посмотрите на рисунок ниже:
Для достижения аналогичного эффекта мы можем использовать единицы измерения, связанные с областью просмотра, и некоторые свойства позиционирования. Вот CSS:
.break-out { width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw; }
Давайте рассмотрим это подробнее, чтобы понять, как все это работает.
1. Добавление width: 100vw
Самый важный шаг, который задаст для изображения ширину, равную 100% области просмотра.
2. Добавление margin-left: -50vw
Чтобы отцентрировать изображение, нам нужно задать для него отрицательное поле с половиной ширины области просмотра.
3. Добавление left: 50%
Наконец, нам нужно будет сдвинуть изображение вправо на 50% ширины его родителя.
Вертикальные и горизонтальные отступы
Еще один интересный пример применения, о котором я подумал — это использование единиц измерения, связанных с областью просмотра, для отступов между элементами. Они могут быть использованы с margin, top, bottom и grid-gap. При этом отступ будет основываться на ширине или высоте области просмотра, что может быть полезно, чтобы сделать макет более динамичным.
Модалы
Возможно использование для модальных окон, которые нам нужно отодвинуть от верхнего края окна просмотра. Часто я делал это с помощью свойства top и использовал либо процентное, либо пиксельное значение. Однако, с помощью единиц измерения, связанных с областью просмотра, мы можем добавить интервал, который может изменяться в зависимости от высоты области просмотра.
.modal-body { top: 20vh; }
Шапка страницы
Шапка — это раздел, который служит введением для страницы. Он часто содержит заголовок и описание, они могут иметь либо фиксированную высоту, либо отступы для верхнего и нижнего краев. Мы можем сделать больше. Например, вот как выглядит CSS:
.page-header { padding-top: 1rem; padding-bottom: 1rem; } @media (min-width: 800px) { .page-header { padding-top: 4rem; padding-bottom: 4rem; } }
Отступы по вертикали на мобильном устройстве слишком малы, а на больших экранах слишком велики. Как насчет использования единиц измерения, связанных с областью просмотра? Давайте попробуем.
.page-header { padding-top: 10vh; padding-bottom: 10vh; } .page-header h2 { margin-bottom: 1.5vh; }
Я использовал vh для отступа перед заголовком страницы и под заголовком. Обратите внимание, как меняется расстояние!
Элементы в сетке
Еще один вариант использования динамического интервала — это элементы в сетке. Это может быть что угодно, например, сетка статей, раздел услуг и т. д. В нашем случае мы рассмотрим, как использовать это для сетки статей.
Используя внутри окна просмотра grid-gap, мы можем получить желаемый результат. Обратите внимание, что я также использовал функцию CSS calc(). Цель использования calc() — получить базовый вертикальный и горизонтальный зазор.
.wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); grid-gap: calc(14px + 1vh) calc(14px + 0.5vw); }
Варианты использования Vmin и Vmax
Исследуя варианты использования этих двух значений, я не нашел ничего, кроме этого на CSS-Tricks. Вариант использования — это верхний и нижний отступы для элемента заголовка страницы. Отступ часто уменьшается, когда область просмотра небольшая (мобильные устройства). Используя vmin, мы можем получить аккуратные верхние и нижние отступы, основанные на меньшем размере области просмотра (ширина или высота).
.page-header { padding: 10vmin 1rem; }
Вертикальные медиа-запросы и единицы измерения, связанные с областью просмотра
Четыре года назад я написал статью о вертикальных медиа-запросах. Я хочу подробнее рассмотреть эту тему, поскольку она связана с данной статьей.
Раздел на всю высоту при альбомной ориентации
Используя вертикальные медиа-запросы, мы можем проверить, имеет ли смартфон или планшет пользователя горизонтальную ориентацию. Если это так, то не имеет смысла задавать раздел, занимающий всю высоту области просмотра с помощью height: 100vh.
Чтобы решить эту проблему, мы можем сделать следующее:
@media (min-height: 400px) { .section { height: 100vh; } }
Или мы можем использовать ориентационный медиа-запрос:
@media (orientation: landscape) { .section { height: 100vh; } }
Соотношение сторон
Мы можем использовать vw для создания адаптивных элементов, которые сохраняют пропорции независимо от размера области просмотра. Давайте рассмотрим это. Нам нужно определиться с необходимым соотношением сторон. Для этого примера я буду использовать 9/16.
section { /* 9/16 * 100 */ height: 56.25vw; }
Использование единиц измерения, связанных с областью просмотра, для графических элементов
Я не уверен, правильно ли я это назвал, но надеюсь, что вы поймете суть из следующих примеров.
Популярная верхняя граница
Вы часто видели эту верхнюю границу, большинство сайтов используют ее в наши дни. В основном, ее цвет совпадает с цветом бренда, что придает индивидуальность.
Давайте представим, что начальное значение для ширины границы 3px. Как преобразовать это фиксированное значение в единицы измерения, связанные с областью просмотра? Ну, вот как рассчитать его vw-эквивалент.
vw = (Pixel Value / Viewport width) * 100
Ширина области просмотра используется для оценки отношения между значением в пикселях и желаемым значением в vw. Для нашего примера вот как добавляется верхняя граница:
.header { border-top: 4px solid #8f7ebc; }
В моем случае ширина области просмотра составляет 1440 (это не фиксированное число, замените его на то, что нравится вам).
vw = (4 / 1440) * 100 = 0.277
.header { border-top: 0.277vw solid #8f7ebc; }
Более того, мы можем использовать базовое значение в пикселях, а единицы измерения, связанные с областью просмотра, могут быть дополнением.
.header { border-top: calc(2px + 0.138vw) solid $color-main; }
Нумерация разделов
Для элементов раздела со счетчиком или значком мы можем использовать единицы измерения, связанные с областью просмотра. Рассмотрим макет ниже:
У нас есть круг, содержащий число, и есть текстовое содержимое. Оба из них должны гибко задаваться в единицах измерения, связанных с областью просмотра. Давайте рассмотрим, как!
/** 1. Using a fluid value for the flex, width, and height properties. 2. The line-height is used to center the text vertically 3. Font size 4. The spacing between the circle and the text **/ .point:before { flex: 0 0 calc(24px + 4vw); /* [1] */ width: calc(24px + 4vw); /* [1] */ height: calc(24px + 4vw); /* [1] */ line-height: calc(24px + 4vw); /* [2] */ font-size: calc(14px + 1vw); /* [3] */ margin-right: calc(10px + 0.5vw); /* [4] */ }
Отслеживание единиц измерения, связанных с областью просмотра
Я создал инструмент, который помогает проверить текущие вычисленные значения в единицах измерения, связанных с областью просмотра.
Я добавил имя класса и свойство для каждого элемента, и при изменении размера области просмотра значения обновляются динамически. Это намного лучше, чем проверка через инструменты разработчика и переход к вычислению для каждого конкретного элемента.
Запуск прокрутки на мобильных устройствах
Существует общая проблема для мобильных устройств, которая представляет собой прокрутку, даже если используется 100vh. Причина в том, что в оке отображается еще адресная строка. Луис Хебрегтс написал об этом статью, в которой описано простое исправление.
.my-element { height: 100vh; /* Fallback for browsers that do not support Custom Properties */ height: calc(var(--vh, 1vh) * 100); } // First we get the viewport height and we multiple it by 1% to get a value for a vh unit let vh = window.innerHeight * 0.01; // Then we set the value in the --vh custom property to the root of the document document.documentElement.style.setProperty('--vh', `${vh}px`);
Доступность имеет значение
При широком использовании в проекте единиц измерения, связанных с областью просмотра, например, для создания целого макета, важна доступность. Когда макет увеличивается / уменьшается, элементы, заданные в этих единицах, не масштабируются, как вы могли ожидать. Это вызовет проблему у пользователей, которые используют для просмотра веб-страниц изменение масштаба.
Согласно этому посту Сары Суэйдан, использование только единиц измерения, связанных с областью просмотра, для определения размера шрифта плохо для доступности. Лучше комбинировать их с фиксированными значениями, как показано ниже:
.title { font-size: calc(16px + .3vw); }
… и это будет работать хорошо. Пожалуйста, удостоверьтесь, что использование единиц измерения, связанных с областью просмотра, является подходящим для того, что вы делаете, и выполняйте тестирование.
Полезные инструменты
Я нашел этот маленький конвертер px в vw, который может помочь вам в ваших проектах.
Автор: Ahmad Shadeed
Источник: https://ishadeed.com
Редакция: Команда webformyself.