Единицы измерения

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

Зачем нужно

Выбор правильных единиц — основа адаптивного дизайна. px хороши для фиксированных размеров, rem — для масштабируемых шрифтов, vw/vh — для полноэкранных секций. Неправильный выбор единиц делает сайт негибким и недоступным.

Где используется

  • rem — размеры шрифтов, отступы, медиа-запросы
  • px — границы, тени, мелкие детали
  • % — ширина контейнеров, адаптивные сетки
  • vw/vh — полноэкранные секции, масштабируемая типографика
  • em — отступы внутри компонентов, относительные к шрифту

Предпосылки

Абсолютные единицы

Не зависят от контекста — всегда одинаковые.

.box {
  /* Пиксели — основная абсолютная единица */
  width: 300px;
  height: 200px;
  border: 1px solid black;

  /* Редко используемые */
  /* 1cm = 37.8px */
  /* 1mm = 3.78px */
  /* 1in = 96px */
  /* 1pt = 1/72 дюйма = 1.33px */
  /* 1pc = 12pt = 16px */
}

/* Print-стили — тут абсолютные единицы уместны */
@media print {
  body {
    font-size: 12pt;
    margin: 2cm;
  }
}

На экранах px — это CSS-пиксели, не физические. На Retina-дисплеях 1 CSS px = 2-3 физических пикселя.

Относительные единицы — шрифтовые

em — относительно font-size родителя

.parent {
  font-size: 20px;
}

.child {
  font-size: 1.5em;  /* 20 * 1.5 = 30px */
  padding: 1em;      /* 30px (относительно СВОЕГО font-size!) */
  margin: 0.5em;     /* 15px */
}

Для font-size: em считается от родителя. Для padding, margin и других — от собственного font-size элемента.

Проблема вложенности:

li { font-size: 1.2em; }

/* <ul> → <li> → 1.2em = 19.2px
        → <ul> → <li> → 1.2em * 1.2em = 23px
                → <ul> → <li> → 1.2^3 = 27.6px
   Размер растёт с каждым уровнем вложенности! */

rem — относительно корневого font-size

:root {
  font-size: 16px; /* базовый размер (обычно по умолчанию в браузерах) */
}

h1 {
  font-size: 2rem;    /* 16 * 2 = 32px — ВСЕГДА */
  margin-bottom: 1rem; /* 16px — ВСЕГДА */
}

p {
  font-size: 1rem;     /* 16px */
  line-height: 1.5rem; /* 24px */
}

.card {
  padding: 1.5rem;     /* 24px */
  margin-bottom: 2rem; /* 32px */
}

rem не зависит от вложенности — предсказуемый и надёжный. Лучший выбор для шрифтов и отступов.

ch — ширина символа «0»

/* Ограничить ширину текста ~60-80 символов для читаемости */
.article {
  max-width: 70ch;
}

/* Ширина инпута для 20 символов */
input {
  width: 20ch;
}

ex — высота строчной «x»

/* Редко используется */
sup {
  font-size: 0.75em;
  vertical-align: 1ex;
}

Относительные единицы — viewport

vw и vh — процент от viewport

/* Полноэкранная секция */
.hero {
  width: 100vw;   /* 100% ширины окна */
  height: 100vh;  /* 100% высоты окна */
}

/* Адаптивная типографика */
h1 {
  font-size: 5vw; /* Масштабируется с шириной окна */
}

/* 1vw = 1% ширины viewport */
/* 1vh = 1% высоты viewport */

vmin и vmax

/* vmin = меньшее из vw и vh */
/* vmax = большее из vw и vh */

/* Квадрат, вписанный в экран */
.square {
  width: 80vmin;
  height: 80vmin;
}

/* Хорошо для адаптивных размеров на любой ориентации */
.responsive-text {
  font-size: 3vmin; /* Не будет слишком мелким в portrait */
}

Новые viewport-единицы (svh, lvh, dvh)

На мобильных устройствах высота viewport меняется при скролле (адресная строка скрывается):

/* svh — Small Viewport Height (адресная строка видна) */
.section-small {
  min-height: 100svh;
}

/* lvh — Large Viewport Height (адресная строка скрыта) */
.section-large {
  min-height: 100lvh;
}

/* dvh — Dynamic Viewport Height (отслеживает текущую высоту) */
.section-dynamic {
  min-height: 100dvh; /* Рекомендуемый для мобильных */
}

/* Аналогично для ширины: svw, lvw, dvw */
/* И для vmin/vmax: svmin, lvmin, dvmin */

100dvh — лучшая замена 100vh для мобильных устройств.

Проценты (%)

Зависят от родительского элемента и свойства:

.parent {
  width: 800px;
  font-size: 20px;
}

.child {
  width: 50%;       /* 400px — от ширины родителя */
  padding: 10%;     /* 80px — от ШИРИНЫ родителя (даже вертикальный!) */
  font-size: 120%;  /* 24px — от font-size родителя */
  line-height: 150%; /* 36px — от font-size САМОГО элемента */
}

padding и margin в % всегда считаются от ширины родителя, даже padding-top и margin-bottom. Это часто удивляет.

Трюк: квадрат через padding

/* Квадрат с соотношением 1:1 */
.square {
  width: 50%;
  padding-top: 50%; /* = ширина, т.к. считается от ширины родителя */
  height: 0;
}

/* Современная альтернатива */
.square-modern {
  width: 50%;
  aspect-ratio: 1 / 1;
}

Когда что использовать

Единица Рекомендация
rem Шрифты, отступы, медиа-запросы — основная единица
px Границы, тени, outline, фиксированные мелкие размеры
em Отступы внутри компонента (масштабируются с font-size)
% Ширина контейнеров, адаптивные сетки
vw/vh Полноэкранные секции, hero-блоки
dvh Мобильные полноэкранные секции
ch Ограничение ширины текста
vmin Адаптивные элементы на любой ориентации

Адаптивная типографика с clamp

/* Минимум 16px, идеально 2.5vw, максимум 24px */
body {
  font-size: clamp(1rem, 2.5vw, 1.5rem);
}

h1 {
  font-size: clamp(2rem, 5vw, 4rem);
}

Частые ошибки

  1. em для шрифтов при вложенности — размер накапливается:
    /* ПЛОХО */
    li { font-size: 1.1em; } /* Вложенные списки растут */
    /* ХОРОШО */
    li { font-size: 1.1rem; }
    
  2. 100vh на мобильных — не учитывает адресную строку:
    /* ПЛОХО */
    .hero { height: 100vh; }
    /* ХОРОШО */
    .hero { height: 100dvh; }
    
  3. % для padding-top — считается от ширины, не от высоты
  4. Фиксированные px для шрифтов — пользователь не сможет масштабировать:
    /* ПЛОХО */
    body { font-size: 14px; }
    /* ХОРОШО */
    body { font-size: 0.875rem; }
    

Практика

  • Создать блок с размерами в px, em, rem, % и сравнить
  • Сделать hero-секцию на 100dvh
  • Применить clamp для адаптивного шрифта
  • Создать ограничение max-width: 70ch для статьи
  • Проверить разницу vw и % на элементе внутри контейнера

Связанные темы

Ресурсы