Единицы измерения CSS: px, em, rem, vw, vh, %, ch, clamp()
Единицы измерения в CSS — абсолютные (px) и относительные (em, rem, vw, vh, %), функция clamp(), когда использовать rem а когда px, подходы к типографике.
Абсолютные единицы
.px { width: 200px; } /* пиксель — самый частый */
.pt { font-size: 12pt; } /* пункт (1pt = 1.33px) — для печати */
.cm { width: 5cm; } /* сантиметр */
.mm { width: 50mm; } /* миллиметр */
px — единственная абсолютная единица, которую вы будете использовать регулярно. Остальные — для печати.
Относительные единицы
em — относительно размера шрифта элемента
.parent {
font-size: 16px;
}
.child {
font-size: 1.5em; /* 24px (16 × 1.5) */
padding: 1em; /* 24px (от своего font-size) */
margin-bottom: 0.5em; /* 12px */
}
Проблема — em вкладываются. Если у родителя font-size: 1.2em, а у ребёнка тоже 1.2em, результат не 1.2× от базового, а 1.2 × 1.2 = 1.44×:
.level-1 { font-size: 1.2em; } /* 19.2px */
.level-2 { font-size: 1.2em; } /* 23.04px (19.2 × 1.2) */
.level-3 { font-size: 1.2em; } /* 27.65px (23.04 × 1.2) */
rem — относительно корневого размера шрифта
rem = root em. Всегда считается от font-size элемента <html>, а не от родителя:
html {
font-size: 16px; /* по умолчанию в большинстве браузеров */
}
.card {
font-size: 1.125rem; /* 18px — от корня, не от родителя */
padding: 1rem; /* 16px */
margin-bottom: 1.5rem; /* 24px */
}
Нет проблемы вложенности — 1.5rem всегда 24px, независимо от глубины.
Когда em, когда rem
- rem — для font-size, margin, padding на уровне компонентов
- em — для внутренних отступов и размеров внутри компонента, которые масштабируются вместе с шрифтом
.button {
font-size: 1rem; /* фиксированный от корня */
padding: 0.5em 1.5em; /* масштабируется с font-size кнопки */
border-radius: 0.25em;
}
% — проценты от родителя
.parent {
width: 1000px;
}
.child {
width: 50%; /* 500px — от ширины родителя */
}
.full-height {
height: 100%; /* работает только если у родителя задана высота */
}
% для высоты работает, если вся цепочка предков имеет заданную высоту вплоть до html:
html, body {
height: 100%;
}
.full-screen {
height: 100%; /* теперь работает */
}
vw и vh — относительно viewport
.hero {
height: 100vh; /* полная высота экрана */
width: 100vw; /* полная ширина экрана */
font-size: 5vw; /* масштабируется с шириной экрана */
}
.sidebar {
width: 25vw; /* четверть экрана */
}
Проблема: 100vw включает ширину скроллбара — может появиться горизонтальная прокрутка. Используйте 100% для ширины или dvw/dvh.
Современные единицы viewport
.full-height {
height: 100dvh; /* dynamic viewport height — учитывает мобильную адресную строку */
}
.hero {
height: 100svh; /* small viewport height — самый маленький viewport */
}
.modal {
height: 100lvh; /* large viewport height — без адресной строки */
}
На мобильных браузерах адресная строка то появляется, то прячется. dvh адаптируется, vh — нет.
ch — ширина символа «0»
.input {
width: 30ch; /* примерно 30 символов моноширинного текста */
}
p {
max-width: 65ch; /* оптимальная длина строки для чтения */
}
Удобно для ограничения ширины текстового блока — исследования показывают, что 45-75 символов в строке оптимально для чтения.
Функция calc()
Математические выражения, можно смешивать единицы:
.sidebar {
width: calc(100% - 250px);
}
.header {
height: calc(100vh - 64px);
}
.grid {
grid-template-columns: repeat(3, calc((100% - 2rem) / 3));
}
Функция clamp()
Минимум, предпочтительное значение, максимум:
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
/* минимум 1.5rem, обычно 4vw, но не больше 3rem */
}
.container {
padding: clamp(1rem, 3vw, 3rem);
width: clamp(320px, 90%, 1200px);
}
clamp() часто заменяет media queries для типографики и отступов.
min() и max()
.element {
width: min(500px, 90%);
/* выберет меньшее: на широком экране 500px, на узком 90% */
font-size: max(1rem, 2vw);
/* выберет большее: не меньше 1rem */
}
Рекомендации
| Что | Единица |
|---|---|
| Font-size | rem |
| Padding/margin | rem или em |
| Ширина контейнера | px (max-width) или % |
| Max-width текста | ch |
| Высота секции | vh / dvh |
| Адаптивные значения | clamp() |
| Расчёты | calc() |
| Border | px |
| Border-radius | px или % (50% для круга) |
| Box-shadow | px |
| Media queries | px или em |
Базовый сброс для работы с rem:
html {
font-size: 100%; /* 16px — не сбрасывайте до 10px, это ломает доступность */
}
body {
font-size: 1rem;
line-height: 1.5;
}
Итог
px— абсолютная, для границ, теней, мелких деталейrem— от корневого шрифта, лучший выбор для font-size и отступовem— от шрифта элемента, для масштабируемых компонентов%— от родителяvw/vh— от viewport,dvhдля мобильныхch— ширина символа, для max-width текстаclamp()— адаптивные значения без media queriescalc()— вычисления с разными единицами