Единицы измерения. Часть 2: единицы окна и вычисления
Чтение — около 7 минут· без учёта практики
В первой части мы разобрали
размеры относительно шрифта и настроили текст сайта Тони. Теперь свяжем размеры с окном браузера: например,
сделаем заголовок крупнее на широком экране и меньше на узком, сохранив удобные границы.
Практику выполним на отдельной странице; файлы my-site в этом уроке менять не нужно.
Единицы относительно окна браузера
Отдельная группа единиц задаёт размеры относительно области просмотра (англ. viewport) — части окна браузера, в которой показывается страница, без панелей самого браузера.
-
1vw (англ. viewport width — ширина области просмотра) = 1% ширины области просмотра. Если ширина области просмотра 1000px, то 1vw = 10px. При изменении ширины окна значение пересчитывается.
-
1vh (англ. viewport height — высота области просмотра) = 1% высоты области просмотра. Если высота области просмотра 500px, то 1vh = 5px.
Единицы vw и vh: попробуйте сами
Размер шрифта и высота блоков заданы в vw и vh. Измените ширину окна браузера или перетащите разделитель между кодом и результатом: размер текста в vw изменится вместе с шириной области результата. Значения в vh зависят от её высоты. Область просмотра здесь — окно результата, а не всё окно браузера.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Единицы vw и vh</title>
<style>
body {
margin: 0; /* без внешнего отступа блок шириной 100% занимает всё окно */
}
.banner {
font-size: 5vw; /* 5% ширины окна */
height: 30vh; /* 30% высоты окна */
background-color: orange;
}
.half {
font-size: 3vw;
width: 50vw; /* половина ширины окна */
height: 20vh;
background-color: gold;
}
</style>
</head>
<body>
<div class="banner">Гуляем с Тони! 5vw, высота 30vh</div>
<div class="half">3vw, ширина 50vw, высота 20vh</div>
</body>
</html>
Первому блоку заданы размер шрифта 5vw (5% ширины области просмотра) и высота 30vh (30% её
высоты). Второму — размер шрифта 3vw, ширина 50vw и высота 20vh. При изменении
размеров окна браузер пересчитывает значения «на лету».
На телефоне высота области просмотра меняется: при прокрутке адресная строка браузера то появляется, то прячется.
Единица vh считается от высоты с убранной панелью, поэтому блок высотой 100vh при видимой
панели частично уходит за край экрана. Для таких случаев есть единицы svh (малая область просмотра,
панель видна), lvh (большая, панель убрана) и dvh (текущая высота). Для блока, который должен помещаться при видимых панелях, подходит min-height: 100svh.
Значение min-height: 100dvh следует за доступной высотой, но может менять размер блока при прокрутке.
Минимальная высота позволяет блоку расти, если текста больше, чем помещается на экране.
Единицы vmin и vmax
Единицы vmin и vmax берут за основу ширину или высоту области просмотра — в зависимости от того, какая из них меньше или больше:
- 1vmin = 1vw или 1vh — меньшее из двух значений.
- 1vmax = 1vw или 1vh — большее из двух значений.
Единицы vmin и vmax: попробуйте сами
Чёрный квадрат — 40% меньшей стороны области просмотра, синий — 40% большей. Сузьте окно браузера или перетащите разделитель между кодом и результатом так, чтобы область результата стала выше, чем шире: размер чёрного квадрата будет рассчитываться от её ширины, а синего — от высоты.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Единицы vmin и vmax</title>
<style>
body {
margin: 0;
}
div {
display: inline-block; /* блоки стоят в строку */
color: white;
}
.min {
width: 40vmin; /* 40% меньшей стороны окна */
height: 40vmin;
background-color: black;
}
.max {
width: 40vmax; /* 40% большей стороны окна */
height: 40vmax;
background-color: blue;
}
</style>
</head>
<body>
<div class="min">40vmin</div>
<div class="max">40vmax</div>
</body>
</html>
Блоки стоят в строку благодаря свойству
display
со значением inline-block. Допустим, область просмотра шириной 400px и высотой 700px. Для первого блока с
классом min меньшая сторона — 400px:
Ширина и высота одинаковы, получается квадрат 160×160px. Для второго блока с классом max берётся большая сторона — 700px:
Единицы окна поддерживаются всеми современными браузерами и пригодятся при адаптивной вёрстке, которую мы рассмотрим
позже в уроке «Адаптивная вёрстка. Часть 1». Размер шрифта только
в vw задавать не стоит: он не реагирует на настройку шрифта пользователя, а на узком экране становится
слишком мелким. Вычислять размеры и ограничивать их помогают CSS-функции. Например, clamp() позволяет
задать размер, который плавно меняется с шириной окна, но остаётся в заданных границах. Разберём эти функции ниже.
Вычисления и границы размера
CSS-функции — это встроенные команды, с помощью которых браузер получает значение свойства из переданных данных.
Функцию записывают как имя с круглыми скобками, внутри которых указывают исходные значения или выражение.
Их называют аргументами. Браузер вычисляет результат функции динамически и использует его как значение свойства.
Если величины, от которых зависит расчёт, меняются — например, ширина окна или размер шрифта, — результат пересчитывается.
Например, в width: calc(100% - 2rem) функция calc() рассчитывает ширину блока.
Когда размер зависит сразу от окна и шрифта, CSS может выполнить расчёт сам.
calc(100% - 2rem) вычитает из доступной ширины два размера шрифта корня;
вокруг знаков + и - нужны пробелы. Можно сочетать совместимые величины,
например длину и процент в свойстве width.
min(100%, 30rem)выбирает меньшее: блок не шире родителя и не шире 30rem.max(1rem, 2vw)выбирает большее: отступ растёт с окном, но не меньше 1rem.clamp(1.5rem, 1rem + 2vw, 2.5rem)задаёт минимум, желаемый размер и максимум. Заголовок плавно меняется между1.5remи2.5rem; сумму внутри можно писать безcalc().
Составляющая в rem учитывает настройку шрифта, а vw — ширину окна.
Это не гарантирует нужное увеличение при любых границах: проверьте текст при масштабе 200% и увеличенном шрифте браузера.
Если заголовок почти не увеличивается, уменьшите долю vw или задайте размер в rem.
Функции calc(), min(), max() и clamp(): попробуйте сами
Сужайте окно результата: ширина текста ограничена min(), заголовок меняется в границах clamp(). Замените верхнюю границу 2.5rem на 3rem и сравните на широком экране.
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Вычисления размеров</title>
</head>
<body>
<main>
<h1>Прогулки с Тони</h1>
<p>Тони любит долгие прогулки в парке. Размер заголовка зависит от окна, а строка текста не растягивается бесконечно.</p>
</main>
</body>
</html>
style.css
main {
width: calc(100% - 2rem);
margin: max(1rem, 2vw) auto;
}
h1 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
p { width: min(100%, 30rem); }
Потренируйтесь
Введите 40 и выберите vmin. Задайте ширину окна 400px и высоту 700px:
получится 160px. Поменяйте ширину и высоту местами — результат сохранится. Затем выберите vw
и повторите сравнение: теперь результат зависит только от ширины. Затем выберите vmax и проверьте расчёт от большей стороны.
Проверьте себя
Выберите ответ — объяснение появится сразу. Ответ можно менять.
Задание
В редакторе — афиша прогулки с Тони. На телефоне заголовок должен оставаться читаемым, а на широком экране
описание не должно растягиваться в длинную строку. Посмотрите образец результата, затем выключите глаз,
чтобы видеть свои изменения. Оформление афиши уже задано в base.css; измените style.css:
- Ограничьте ширину абзаца меньшим из значений
100%и30remс помощьюmin(). - Задайте заголовку размер через
clamp(): минимум1.5rem, желаемое значение1rem + 2vw, максимум2.5rem.
Ожидаемый результат: при расширении области результата заголовок растёт, но останавливается на верхней
границе; при сужении не становится меньше нижней. Абзац занимает доступную ширину, пока она меньше
30rem, а затем перестаёт расширяться. Перетащите разделитель между кодом и результатом и проверьте
оба состояния. При размере шрифта корня 16px границы заголовка — 24px и 40px, предельная ширина абзаца — 480px.
Выполните задание
Условие задания
base.css
/* Оформление афиши. Размер заголовка и ширина описания задаются в style.css. */
body {
margin: 16px;
background: #f7f2e8;
color: #263d32;
font-family: Arial, sans-serif;
line-height: 1.6;
}
.eyebrow {
color: #5b6250;
letter-spacing: 0.08em;
text-transform: uppercase;
}
h1 {
margin: 16px 0;
line-height: 1.15;
}
p {
box-sizing: border-box;
padding: 16px;
border-left: 4px solid #b66324;
background: #fffdf8;
}
footer {
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #c5c9b8;
}
index.html
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Прогулка с Тони</title>
</head>
<body>
<header>
<small class="eyebrow">Клуб неспешных прогулок</small>
<h1>За новыми запахами!</h1>
</header>
<p>Тони зовёт исследовать парк: заглянуть под старый дуб, послушать уток у пруда и найти самую длинную палку.
Возьмите воду, удобную обувь и хорошее настроение — торопиться сегодня некуда.</p>
<footer>
<strong>Воскресенье · 10:00</strong><br>
Встречаемся у входа в парк<br>
<small>Маршрут: 2 км · Темп: сколько нужно Тони</small>
</footer>
</body>
</html>
style.css
h1 {
font-size: 2rem;
}
p {
width: 100%;
}
Для самопроверки откройте решение и сравните правила. При ширине области результата 400px желаемый размер
заголовка — 16px + 8px = 24px; при 800px — 32px; при 1600px сумма равна 48px, но ограничение оставит 40px.
Увеличьте масштаб браузера до 200% и убедитесь, что текст остаётся читаемым. Решение можно скопировать или
скачать и проверить в отдельной учебной папке, сохранив my-site для следующего урока.
История единиц окна
Поддержка vw, vh, vmin и vmax в старых браузерах
Единицы окна появились в браузерах в начале 2010-х годов, и долгое время их поддержка была неполной. Opera Mini и
UC Browser for Android их не поддерживали. Internet Explorer 9 понимал вместо vmin устаревшую запись
vm; Internet Explorer 10 и 11 и Edge 12–14 не поддерживали vmax. В iOS Safari стабильная
поддержка появилась с 8-й версии: в 6-й не было vmax, в 7-й некорректно работала vh.
Сегодня vw, vh, vmin и vmax работают во всех современных
браузерах. Единицы svh, lvh и dvh появились в 2022 году и тоже
поддерживаются современными браузерами.