HTML & CSS

Розміри у CSS: повний довідник одиниць і ключових слів

Глибокий огляд усіх одиниць вимірювання CSS: абсолютні (px), відносні (em, rem), viewport (vw, vh, dvh), контейнерні (cqw), intrinsic keywords (min-content, max-content, fit-content), функції min(), max(), clamp(), aspect-ratio, логічні властивості та fr.

Розміри у CSS: повний довідник одиниць і ключових слів

Чому width: 200px — це лише початок

Уявіть такий сценарій: дизайнер передає вам макет. Кнопка має бути «великою». Картка — «половина екрана». Заголовок — «читабельним на будь-якому пристрої». І ось ви відкриваєте CSS і бачите дикий зоопарк: px, em, rem, vw, vh, dvh, cqw, fr, %, ch, min-content... Котре з них «правильне»?

Відповідь незручна: усі вони правильні — просто для різних задач. Вибір одиниці вимірювання — це архітектурне рішення, яке впливає на адаптивність, доступність та передбачуваність вашого коду.

У попередній статті ми дізналися, що кожен елемент — це коробка з чотирма шарами. Тепер навчимося точно контролювати розмір цієї коробки — не тільки через width: 200px, але й через десятки інших інструментів, які CSS надає для різних контекстів.

Loading diagram...
graph TD
    A["CSS Розміри"] --> B["Абсолютні\npx, pt, cm, mm"]
    A --> C["Відносні шрифтові\nem, rem, ch, ex"]
    A --> D["Viewport\nvw, vh, dvh, svh, lvh"]
    A --> E["Контейнерні\ncqw, cqh, cqi"]
    A --> F["Intrinsic keywords\nmin-content, max-content\nfit-content, auto"]
    A --> G["Функції\ncalc(), min(), max()\nclamp()"]
    A --> H["Grid-специфічні\nfr"]
    style A fill:#6366f1,color:#fff,stroke:#4f46e5
    style B fill:#3b82f6,color:#fff,stroke:#2563eb
    style C fill:#10b981,color:#fff,stroke:#059669
    style D fill:#f59e0b,color:#fff,stroke:#d97706
    style E fill:#ec4899,color:#fff,stroke:#db2777
    style F fill:#8b5cf6,color:#fff,stroke:#7c3aed
    style G fill:#06b6d4,color:#fff,stroke:#0891b2
    style H fill:#64748b,color:#fff,stroke:#475569

Абсолютні одиниці (Absolute Units)

Абсолютні одиниці — це фіксовані розміри, які не залежать від контексту: ні від батьківського елемента, ні від розміру вікна браузера, ні від налаштувань користувача.

px — піксель, якого не існує

px — найпоширеніша одиниця CSS, і водночас найбільш оманлива за назвою. Жоден сучасний пристрій не відображає «один CSS-піксель» як буквально один фізичний піксель екрана.

Фізичний піксель vs CSS-піксель:

Сучасні екрани мають Device Pixel Ratio (DPR) — коефіцієнт, що показує, скільки фізичних пікселів відповідає одному CSS-пікселю. На MacBook Pro з Retina-дисплеєм DPR = 2: 1px CSS = 2×2 = 4 фізичні пікселі. На iPhone 15 Pro — DPR = 3.

Loading diagram...
graph LR
    A["1px CSS"] --> B["DPR 1\n(звичайний монітор)\n1 фіз. піксель"]
    A --> C["DPR 2\n(Retina)\n4 фіз. пікселі"]
    A --> D["DPR 3\n(iPhone Pro)\n9 фіз. пікселів"]
    style A fill:#6366f1,color:#fff
    style B fill:#64748b,color:#fff
    style C fill:#3b82f6,color:#fff
    style D fill:#ec4899,color:#fff

Саме тому зображення мають бути вдвічі (або втричі) більшими за відображуваний розмір, щоб виглядати чітко на Retina-екранах.

Коли використовувати px:

  • border: 1px solid — тонкі декоративні лінії
  • border-radius: 4px — невеликі заокруглення
  • box-shadow — тіні
  • outline-offset — зсув обідка фокусу
  • Розміри іконок (width: 24px) у контексті, де масштабування небажане
🔒localhost:3000

Друкарські одиниці: pt, cm, mm, in, pc

Ці одиниці мають чіткий фізичний зміст, але у веб-розробці майже не використовуються — крім @media print:

ОдиницяПовна назваЕквівалент
ptPoint1/72 дюйма ≈ 1.33px
pcPica12pt ≈ 16px
inInch (дюйм)96px
cmCentimeter~37.8px
mmMillimeter~3.78px
/* Єдиний розумний контекст для друкарських одиниць */
@media print {
  body {
    font-size: 12pt; /* Читабельно на папері */
  }
  h1 {
    font-size: 24pt;
  }
  .page-break {
    page-break-before: always;
  }
}
У веб-контексті px завжди кращий за pt чи cm. Ці одиниці мають сенс лише якщо ви готуєте стилі для друку, де фізичний розмір критичний.

Відносні шрифтові одиниці (Font-relative Units)

На відміну від абсолютних, ці одиниці обчислюються відносно розміру шрифту — або поточного елемента, або кореневого.

em — магія каскаду

em вираховується відносно font-size самого елемента (або батьківського, якщо font-size не задано явно). На перший погляд, здається зручним, але має небезпечний побічний ефект — ефект каскадного множення.

🔒localhost:3000

Зверніть увагу: em множиться при кожному вкладенні. Три рівні з 1.2em — і текст виріс майже вдвічі. Це небажана поведінка у більшості сценаріїв.

Де em таки корисний: властивості елемента, що мають бути пропорційні до його власного шрифту:

.button {
  font-size: 1rem;
  padding: 0.6em 1.2em;  /* padding масштабується разом із font-size кнопки */
  border-radius: 0.3em;
}

.button--large {
  font-size: 1.25rem;
  /* padding і border-radius автоматично стануть більшими через em */
}

rem — надійна альтернатива

rem (root em) завжди вираховується відносно font-size кореневого елемента <html> (:root). За замовчуванням — 16px, але користувач може змінити це у налаштуваннях браузера.

:root {
  font-size: 16px; /* базовий розмір — 1rem = 16px */
}

/* Або зручний трюк: 1rem = 10px */
:root {
  font-size: 62.5%; /* 62.5% від 16px = 10px */
}
/* Але! Це ламає налаштування доступності користувача — не рекомендується */
Не задавайте font-size: 62.5% або font-size: 10px на :root. Це скасовує налаштування розміру шрифту у браузері, яке використовують люди зі слабким зором. Принцип доступності: базовий font-size :root має бути відносним або не задаватися взагалі.

Правило великого пальця: rem для font-size, spacing, width/height компонентів; em для padding/margin всередині компонента, що мають бути пропорційні до шрифту.

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

1ch = ширина символу нуля (0) у поточному шрифті. Ідеальна одиниця для обмеження ширини текстових блоків:

/* Класичний патерн читабельного тексту */
.article-body {
  max-width: 65ch; /* ~65 символів у рядку — оптимум для читання */
  margin-inline: auto;
}
🔒localhost:3000

ex, lh, rlh, cap — спеціалізовані шрифтові одиниці

ОдиницяЗначенняТипове застосування
exВисота рядкової літери (≈ висота «x»)Вирівнювання дрібних деталей
capВисота заголовної літериОрнаменти, декоративні елементи
lhВисота рядка (line-height) елементаВідступи кратні висоті рядка
rlhВисота рядка кореневого елементаВертикальний ритм
/* Практичний приклад: drop cap (буквиця) */
.dropcap::first-letter {
  font-size: 3cap; /* Висота 3 заголовних літер */
  float: left;
  margin-right: 0.1em;
  line-height: 1;
  font-weight: bold;
  color: #6366f1;
}

/* Відступи між секціями кратні висоті рядка */
.section + .section {
  margin-top: 2lh;
}

Viewport-відносні одиниці

Viewport — це видима область браузерного вікна. Viewport-одиниці дозволяють задавати розміри відносно цієї області.

vw та vh — базові viewport-одиниці

  • 1vw = 1% ширини viewport
  • 1vh = 1% висоти viewport
  • 100vw = повна ширина, 100vh = повна висота
🔒localhost:3000

Проблема vh на мобільних: адрес-бар

Найвідоміший підводний камінь: на мобільних браузерах 100vh включає простір, що займає адресний рядок (URL bar), навіть коли він видимий. При скролі адрес-бар ховається, і 100vh раптово стає більшим. Результат — елементи, що "стрибають" або обрізаються.

Loading diagram...
graph LR
  A["Сторінка завантажена\n(адресний рядок видимий)"] -->|"100vh = вся висота\nвключно з адрес-баром"| B["Hero виходить\nза межі екрана ❌"]
  C["Після прокручування\n(адресний рядок прихований)"] -->|"100vh збільшується"| D["Hero 'стрибає' ❌"]
  style B fill:#ef4444,color:#fff
  style D fill:#ef4444,color:#fff

svh, lvh, dvh — нові одиниці viewport (2022+)

Специфікація CSS Values Level 4 ввела три нових варіанти, що вирішують проблему адрес-бара:

ОдиницяНазваЩо враховує
svhSmall Viewport HeightМінімальна висота viewport (адрес-бар видимий)
lvhLarge Viewport HeightМаксимальна висота viewport (адрес-бар прихований)
dvhDynamic Viewport HeightДинамічна — оновлюється в реальному часі
svw, lvw, dvwАналоги по шириніТе саме для горизонталі
vmin, vmaxMin / MaxМенша / більша зі сторін viewport
🔒localhost:3000

Рекомендація для full-page layouts:

/* Замість 100vh — використовуйте dvh або svh */
.hero {
  min-height: 100dvh; /* динамічно адаптується */
}

/* Або більш консервативно — svh для стабільності */
.fullscreen-modal {
  height: 100svh; /* завжди вміщується, навіть з адрес-баром */
}

Контейнерні одиниці (Container Query Units)

Це одне з найреволюційніших нововведень сучасного CSS. Якщо viewport-одиниці реагують на розмір вікна браузера, контейнерні одиниці реагують на розмір найближчого контейнера.

Проблема, яку вони вирішують

Уявіть компонент картки, що розміщується в різних контейнерах: одного разу — у широкому main, іншого — у вузькому aside. З vw або % вона реагує на viewport, але не знає, у якому конкретно місці вона знаходиться. Контейнерні одиниці — знають.

🔒localhost:3000

Синтаксис контейнерних одиниць

Спочатку потрібно зареєструвати контейнер, а потім використовувати одиниці всередині нього:

/* Крок 1: оголошуємо елемент контейнером */
.card-wrapper {
  container-type: inline-size; /* або: size | normal */
  container-name: card; /* необов'язково — для іменованих контейнерів */
}

/* Скорочення */
.card-wrapper {
  container: card / inline-size;
}

/* Крок 2: використовуємо cq-одиниці всередині */
.card-title {
  font-size: 5cqi; /* 5% від inline-size контейнера */
}
ОдиницяРозшифровкаВідносно
cqwContainer Query WidthШирина контейнера
cqhContainer Query HeightВисота контейнера
cqiContainer Query InlineInline-вісь контейнера
cqbContainer Query BlockBlock-вісь контейнера
cqminContainer Query MinМенша зі сторін
cqmaxContainer Query MaxБільша зі сторін
container-type: inline-size — найпоширеніший варіант: контейнер реагує лише на ширину. size — реагує і на ширину, і на висоту, але вимагає явно заданої висоти контейнера. Підтримка: Chrome 105+, Firefox 110+, Safari 16+

Intrinsic розміри: коли вміст диктує розмір

CSS дозволяє передати рішення про розмір самому вмісту — через спеціальні ключові слова. Це принципово різний підхід: замість того, щоб ми вказували число, браузер сам обчислює розмір, виходячи з вмісту елемента.

min-content — мінімум без втрат

min-content — це найменший розмір, при якому вміст не втрачається. Для тексту це ширина найдовшого нерозривного слова або рядка. Для зображення — його природна ширина.

max-content — без переносів взагалі

max-content — це розмір, при якому весь вміст розміщується в один рядок без жодного переносу.

fit-content — компромісне рішення

fit-content — веде себе як max-content доти, доки не досягне доступного простору. Тоді починає переносити вміст, як min-content. Фактично: min(max-content, max(min-content, available-space)).

fit-content(value) — функція з обмеженням

fit-content(300px) — те саме, що fit-content, але з явним обмеженням максимуму: не більше 300px.

🔒localhost:3000

Особливо важливі ці ключові слова у Grid Layout у рядку grid-template-columns:

.layout {
  display: grid;
  /* Перша колонка — під вміст, друга — залишок */
  grid-template-columns: max-content 1fr;
}

.nav {
  display: grid;
  /* Кожна колонка — під свій вміст, але не більше 200px */
  grid-template-columns: repeat(auto-fill, fit-content(200px));
}

width, height та їх min-/max- варіанти

Паттерн: fluid container

Один із найважливіших патернів у сучасній верстці — елемент, що займає все доступне місце, але не перевищує певний максимум і не стискається нижче певного мінімуму:

/* Класичний fluid container */
.container {
  width: 100%;          /* займає все доступне */
  max-width: 1200px;    /* але не більше 1200px */
  margin-inline: auto;  /* центруємо */
  padding-inline: 1rem; /* горизонтальні відступи */
}
🔒localhost:3000

Чому height: 100% не завжди працює

Це одне з найчастіших питань новачків. Якщо задати height: 100%, але батьківський елемент не має явно заданої висоти — нічого не відбудеться. Браузер не може обчислити 100% від auto.

🔒localhost:3000

Рішення для height: 100%: батько повинен мати явну висоту, або ж використати display: flex / display: grid з flex: 1 на дочірньому елементі.


Логічні властивості (Logical Properties)

Традиційні CSS-властивості — width, height, margin-left, padding-top — прив'язані до фізичних осей: горизонталь та вертикаль. Але у світі існують мови, що пишуться справа наліво (арабська, іврит) або зверху вниз (японська). Для них поняття «ліво» та «право» втрачають сенс.

Логічні властивості оперують відносними осями: inline (завжди вздовж напрямку тексту) та block (перпендикулярно тексту).

ФізичнаЛогічнаДля writing-mode: horizontal-tb
widthinline-sizeгоризонталь
heightblock-sizeвертикаль
margin-leftmargin-inline-startліво (для LTR) або право (для RTL)
margin-rightmargin-inline-endправо (для LTR) або ліво (для RTL)
padding-toppadding-block-startверх
margin-top + margin-bottommargin-blockскорочення: верх+низ
margin-left + margin-rightmargin-inlineскорочення: ліво+право
🔒localhost:3000
Використовуйте логічні скорочення замість фізичних у компонентах, що потенційно можуть бути використані в міжнародних проєктах:
/* ❌ Фізичне — ламається в RTL */
.card { margin-left: auto; margin-right: auto; }

/* ✅ Логічне — працює скрізь */
.card { margin-inline: auto; }

CSS-функції для розмірів: calc(), min(), max(), clamp()

calc() — арифметика між будь-якими одиницями

calc() дозволяє змішувати різні одиниці в одному виразі — те, що неможливо зробити статичним числом:

.element {
  /* Займаємо всю ширину, мінус фіксований sidebar */
  width: calc(100% - 280px);

  /* Відступ кратний розміру шрифту, але з фіксованим мінімумом */
  padding: calc(1rem + 5px);

  /* Вертикальний відступ пропорційний viewport */
  margin-top: calc(5vh - 1rem);
}
🔒localhost:3000

min() та max() — умовні розміри

min(a, b) повертає менше з двох значень. max(a, b)більше.

/* min(): не більше за 600px, але адаптується на менших екранах */
.card {
  width: min(100%, 600px);
}

/* max(): не менше за 200px, але розширюється */
.sidebar {
  width: max(200px, 20%);
}
🔒localhost:3000

clamp() — fluid scaling

clamp(min, preferred, max) — найпотужніша з трьох. Вона обмежує значення знизу та зверху, але всередині діапазону використовує будь-який вираз — часто viewport-залежний. Це основа fluid typography та fluid spacing.

/* fluid font-size: мінімум 1rem, максимум 2rem, а між — масштабується з viewport */
h1 {
  font-size: clamp(1rem, 2.5vw + 0.5rem, 2rem);
}

/* fluid padding */
.section {
  padding: clamp(1.5rem, 5vw, 4rem);
}
🔒localhost:3000

aspect-ratio — фіксоване співвідношення сторін

До появи aspect-ratio підтримка фіксованого пропорційного розміру вимагала хаку з padding-top (так звана «padding-bottom trick»). Тепер це одна властивість.

/* 16:9 для відео */
.video-wrapper {
  width: 100%;
  aspect-ratio: 16 / 9;
}

/* Квадратна картка */
.square-card {
  aspect-ratio: 1;
}

/* Золотий перетин */
.golden-ratio {
  aspect-ratio: 1.618 / 1;
}

/* Природне співвідношення зображення */
img {
  aspect-ratio: auto; /* використовує intrinsic ratio зображення */
}
🔒localhost:3000

fr — дробова одиниця Grid

fr (fractional unit) — особлива одиниця, що існує лише в CSS Grid. Вона означає «частку вільного простору» після того, як всі фіксовані розміри розподілені.

.grid {
  display: grid;
  /* Три рівні колонки */
  grid-template-columns: 1fr 1fr 1fr;

  /* Або: перша фіксована, решта — рівні частки */
  grid-template-columns: 200px 1fr 2fr;
  /* 1fr отримає 1/3 вільного простору, 2fr — 2/3 */
}
🔒localhost:3000
fr вираховується після розподілу фіксованих розмірів і gap. Тому grid-template-columns: 200px 1fr з gap: 1rem дасть 1fr = (100% - 200px - 1rem). Не можна використовувати fr поза Grid — лише в grid-template-* та grid властивостях.

Зведена таблиця: яку одиницю коли використовувати

ЗадачаРекомендована одиницяЧому
font-size компонентівremПропорційно налаштуванням браузера
padding/margin всередині компонентаemМасштабується з font-size компонента
spacing між компонентамиremСтабільно, незалежно від вкладення
Ширина контейнера (fluid)% + max-widthАдаптивно + обмежено
Full-height сторінка100dvhБез проблем з mobile адрес-баром
Responsive typographyclamp() або vw+remFluid масштабування
Ширина тексту для читанняchПропорційно символам
Відступи, що ростуть з viewportclamp()Fluid spacing
Grid-колонкиfr + minmax()Native grid units
Компоненти в різних контейнерахcqi, cqwContainer-aware
Тіні, border, декоративні деталіpxФіксована чіткість
Мінімальний/максимальний розмірmin(), max()Умовна логіка
Aspect ratioaspect-ratioНативна підтримка
Логічні відступи (i18n)margin-inline, padding-blockRTL-сумісність

Практика

Рівень 1 — Базовий: виправте розміри

Дано зламаний CSS. Знайдіть і виправте помилки:

<div class="parent">
  <div class="child">Я маю займати всю висоту батька</div>
</div>

<p class="text">Цей текст занадто широкий для читання на великих екранах</p>

<div class="hero">Hero секція на весь екран</div>
/* ❌ Зламаний CSS — знайдіть і виправте 3 помилки */
.parent {
  border: 2px solid blue;
  /* Немає висоти */
}
.child {
  height: 100%;   /* не працює без висоти у батька */
  background: lightblue;
}

.text {
  width: 100%;    /* занадто широкий для читання */
}

.hero {
  height: 100vh;  /* проблема на мобільних */
}

Очікуване рішення:

.parent { border: 2px solid blue; height: 200px; }
.child  { height: 100%; background: lightblue; }
.text   { max-width: 65ch; margin-inline: auto; }
.hero   { min-height: 100dvh; }

Рівень 2 — Fluid typography з clamp()

Реалізуйте адаптивну типографічну шкалу для статті, де заголовки та текст масштабуються між мінімальним та максимальним розміром залежно від ширини viewport. Вимоги:

  • h1: від 1.75rem до 3.5rem
  • h2: від 1.25rem до 2rem
  • p: від 0.9rem до 1.125rem
  • Горизонтальний padding секцій: від 1rem до 5rem

Рівень 3 — Компонент картки з Container Queries

Створіть компонент картки, що автоматично змінює layout:

  • У вузькому контейнері (< 300px): вертикальний layout, дрібний текст
  • У середньому контейнері (300px–500px): горизонтальний layout, середній текст
  • У широкому контейнері (> 500px): горизонтальний layout з більшою картинкою, великий текст з описом

Використовуйте container-type, cqi для шрифту та @container для layout.


Підсумок

CSS-розміри — це не просто числа: це система рішень, де кожна одиниця відповідає на певне запитання. Ось головне, що варто запам'ятати:

📏 Абсолютні (px)

Для фіксованих деталей: border, shadow, border-radius, іконки. Не для font-size та layout spacing.

🔤 Шрифтові (rem/em)

rem — для font-size та spacing компонентів. em — для padding/margin всередині компонента, що має масштабуватись з текстом. ch — для ширини текстового блоку.

📱 Viewport (dvh/vw)

dvh замість vh для full-height layouts на мобільних. vw + clamp() для fluid typography.

📦 Контейнерні (cqi)

cqi/cqw для компонентів, що розміщуються в різних контейнерах. Завжди потребують container-type на батькові.

🧠 Intrinsic (min-content)

min-content, max-content, fit-content — дозвольте вмісту самому вирішувати. Дуже корисні в Grid.

⚡ Функції (clamp)

min(), max(), clamp() — умовна логіка в CSS без медіа-запитів. clamp() = fluid scaling між двома точками.