Ширина и высота блока в CSS: width, height, box-sizing, min/max

Ширина и высота блока в CSS: width, height, box-sizing, min/max Полезное

Ширина блока в CSS задается свойством width, высота — свойством height. Если их не указывать, действует значение auto: обычный блочный элемент (div, p, section) растягивается на всю доступную ширину родителя, а по высоте подстраивается под содержимое.

Важная оговорка сразу: число в width — это еще не итоговая ширина на экране. Что именно оно измеряет, решает свойство box-sizing. Ниже — минимальный рабочий пример, затем разбор единиц, ограничений min/max, процентов, vw/dvh и ключевых слов auto и fit-content. Все размеры в примерах замерены в Chrome 153 (headless, проверка 24.09.2026).

Мини-словарь: из чего складывается размер блока

  • content — область содержимого (текст, вложенные элементы);
  • padding — внутренний отступ между содержимым и рамкой;
  • border — рамка;
  • margin — внешний отступ; в ширину самого блока не входит, но занимает место в родителе.

Итоговая ширина блока на экране = content + padding слева и справа + border слева и справа. Свойство box-sizing определяет, к какой части этой суммы относится значение width.

Минимальный пример: контейнер и карточка

<!doctype html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { margin: 0; }
    .container { max-width: 1200px; margin-inline: auto; padding-inline: 16px; }
    .card { width: 300px; padding: 20px; border: 2px solid #ccc; }
  </style>
</head>
<body>
  <div class="container">
    <div class="card">Карточка</div>
  </div>
</body>
</html>

Что получится: при окне 1000px контейнер занимает все 1000px, при окне 1600px — ровно 1200px и стоит по центру. Карточка в обоих случаях шириной ровно 300px, хотя у нее есть отступы и рамка.

Разбор по строкам:

  1. box-sizing: border-box для всех элементов — width включает padding и border, поэтому 300px остаются 300px.
  2. У .container нет width: он равен ширине окна, пока не упрется в max-width: 1200px.
  3. margin-inline: auto делит свободное место поровну слева и справа — так блок центрируется.
  4. padding-inline: 16px не дает тексту прилипать к краям экрана на телефоне.

Какие элементы вообще принимают width и height

Ширину можно задать не любому элементу. Проверка в браузере для width: 300px; height: 100px:

Элемент Пример Результат замера
Строчный (display: inline) span, a 35x18px — размеры проигнорированы, блок по тексту
Строчно-блочный (inline-block) span с display: inline-block 300x100px — размеры применились
Блочный (block) div, p 300x100px
Заменяемые и элементы форм img, video, input размеры применяются, хотя элемент строчный; у input итог 308x106px — к width в content-box прибавились его padding и рамка

Отсюда правило: если width у ссылки или span «не работает», поменяйте display на inline-block или block. Внутри flex- и grid-контейнера дочерние элементы становятся блочными по поведению, и width у них тоже работает.

box-sizing: content-box против border-box

По умолчанию у div, p, section, input и большинства других элементов box-sizing: content-box — width задает только область содержимого. Исключения задает стиль браузера: у button, select, чекбоксов и радиокнопок в Chrome уже border-box. Сравним два блока с одинаковыми width: 200px; padding: 20px; border: 2px solid:

.a { box-sizing: content-box; width: 200px; padding: 20px; border: 2px solid; }
.b { box-sizing: border-box;  width: 200px; padding: 20px; border: 2px solid; }

Замер: блок .a шириной 244px (200 + 20 + 20 + 2 + 2), блок .b — ровно 200px (на содержимое остается 156px). При этом getComputedStyle(el).width у обоих возвращает 200px — итоговую ширину на экране показывает getBoundingClientRect().width или offsetWidth.

content-box (умолчание) border-box
Что измеряет width только содержимое содержимое + padding + border
Итог при width 200, padding 20, border 2 244px 200px
Когда удобно редкие случаи, где важен точный размер содержимого почти вся современная верстка

Поэтому в большинстве проектов в начале CSS стоит сброс *, *::before, *::after { box-sizing: border-box; }. Margin в обоих режимах в ширину не входит.

Проценты: от чего они считаются

width: 50% считается от ширины содержащего блока (обычно — родителя). С высотой сложнее:

.parent-fixed { height: 300px; }
.parent-fixed .child { height: 50%; }   /* 150px */

.parent-auto .child { height: 50%; }    /* родитель без height: процент не работает */

Замер: в первом случае ребенок получил 150px, во втором — только высоту своей строки текста (18px при шрифте 16px и line-height: normal, с другим шрифтом число будет другим). Если у родителя высота не задана явно (auto), процентная height ребенка обычно ведет себя как auto. Исключения — абсолютно позиционированные элементы и флекс/грид-раскладки, где высота родителя известна из раскладки.

Еще одна ловушка: вертикальные padding и margin в процентах считаются тоже от ширины родителя, а не от высоты. padding-top: 10% в родителе шириной 600px дал 60px.

Ошибка: width 100% и отступы

Неверно (режим content-box, родитель 600px):

.box { width: 100%; padding: 20px; }

Результат замера: блок шириной 640px вылезает за родителя на 40px. Исправление — любой из двух вариантов: добавить box-sizing: border-box или просто убрать width: 100%. Блочный элемент с width: auto и так занимает всю ширину: замер без width — ровно 600px вместе с отступами.

Колонки в процентах

Старый прием — две колонки 30% и 70% через float. В режиме content-box с padding: 20px сумма выходит 340 + 740 = 1080px в контейнере 1000px, и правая колонка переезжает на следующую строку. Во flex-контейнере она не переедет, но flex сожмет обе колонки: замер показал 316px и 684px вместо 300 и 700. С border-box получились ровно 300px и 700px.

Для раскладки страницы сейчас чаще берут flex или grid: например, grid-template-columns: 280px 1fr — фиксированная боковая колонка и основная на остаток ширины.

min-width и max-width: гибкая ширина с границами

max-width запрещает блоку стать шире значения, min-width — уже. Это основа адаптивного контейнера: блок сжимается вместе с окном, но на широком экране не растягивается строками по 200 символов.

.page { max-width: 1320px; margin-inline: auto; }  /* сжимается, скролла нет */
.table-wrap { min-width: 600px; }                  /* уже 600px не станет */

Если окно уже, чем min-width, блок перестает сжиматься, и у страницы появляется горизонтальная прокрутка. Для таблиц лучше обернуть их в контейнер с overflow-x: auto, чтобы прокручивалась только таблица.

Приоритет при конфликте: min-width сильнее max-width, а оба сильнее width. Проверка width: 100px; min-width: 300px; max-width: 200px дала блок шириной 300px. То же действует для min-height и max-height.

Ошибка: фиксированная высота и длинный текст

Блок с height: 40px и четырьмя строками текста остался высотой 40px, а содержимое (96px, по scrollHeight) вылезло наружу и наехало на следующий блок. Если высота нужна «не меньше чем», используйте min-height: 40px: блок растет вместе с текстом. Фиксированную height оставляйте для элементов с заранее известным содержимым — иконок, аватаров, полос прокрутки с overflow: auto.

vw, vh и dvh: размеры от окна браузера

Единицы вьюпорта считаются от окна, а не от родителя: 1vw = 1% ширины окна, 1vh = 1% высоты.

  • 100vw может вызвать горизонтальную прокрутку. В ширину вьюпорта входит полоса прокрутки. Замер в Chrome при окне 1000px и классической полосе 15px: блок width: 100vw — 1000px, блок width: 100% — 985px, у страницы появился горизонтальный скролл на 15px. Для «на всю ширину» обычно достаточно width: 100% или вовсе auto. На macOS и мобильных с накладными полосами прокрутки разницы не видно — поэтому ошибка часто всплывает только у пользователей Windows. В Chrome 145+ есть и другой выход: если у html задано scrollbar-gutter: stable или overflow-y: scroll, единицы vw сами вычитают ширину полосы; в браузерах без этой поддержки 100vw по-прежнему включает полосу.
  • 100vh на телефоне. В мобильных браузерах панель адреса то появляется, то прячется, и 100vh может оказаться выше видимой области. Для этого есть единицы svh (малый вьюпорт, панели показаны), lvh (большой, панели скрыты) и dvh (динамический, меняется вместе с панелями).

Практичный вариант для первого экрана:

.hero { min-height: 100vh; min-height: 100dvh; }

Первая строка — запасной вариант для старых браузеров, вторая перекрывает ее там, где dvh поддерживается. На десктопе без панелей все три единицы совпадают: в прогоне 100vh, 100svh, 100lvh и 100dvh дали одинаковую высоту.

auto, fit-content, min-content, max-content

Кроме чисел, width принимает ключевые слова. Они задают ширину через содержимое, а не через число.

Значение Что делает Замер (текст «Очень длинное слово и еще два»)
auto блок занимает всю ширину родителя 600px (ширина родителя)
max-content ширина текста в одну строку без переносов 244px
min-content ширина самого длинного слова, остальное переносится 64px, 4 строки
fit-content как max-content, но не шире родителя кнопка «Кнопка» с padding 8px — 73px

fit-content удобен для плашек, тегов и кнопок, которые должны быть по размеру текста, но оставаться блоком на отдельной строке. Для пропорций вместо подбора высоты есть aspect-ratio: width: 300px; aspect-ratio: 16 / 9 дал высоту 168.75px.

Ошибка: flex-элемент не сжимается

Во flex-контейнере шириной 300px два элемента с flex: 1, в первом — длинная строка без пробелов. Замер: первый элемент растянулся до 463px и вылез за контейнер. Причина — у flex-элементов по умолчанию min-width: auto, то есть «не уже содержимого». Исправление — min-width: 0 у элемента (плюс overflow-wrap: anywhere или overflow: hidden для самого текста): после него оба элемента стали по 150px.

Если размер блока не такой, как ожидали

Симптом Частая причина Что сделать
width у ссылки или span не работает строчный элемент display: inline-block или block
Блок шире заданного на padding + border content-box box-sizing: border-box
height: 50% ничего не меняет у родителя height: auto задать высоту родителю или перейти на flex/grid
Горизонтальный скролл по всей странице 100vw, width: 100% с отступами, min-width заменить на 100%/auto, проверить border-box
Текст вылезает из блока фиксированная height min-height вместо height
Flex-элемент раздувает строку min-width: auto у flex-элемента min-width: 0

Для диагностики откройте DevTools (F12), выделите элемент и посмотрите схему box model на вкладке Computed: там видно, сколько пикселей дает содержимое, padding, border и margin.

Выводы

  • Ширина блока задается width, высота — height; по умолчанию auto: блок во всю ширину родителя и по высоте содержимого.
  • Итоговый размер зависит от box-sizing: в content-box padding и border прибавляются к width, в border-box входят в него.
  • Проценты по ширине считаются от родителя, процентная высота требует известной высоты родителя; вертикальные padding и margin в процентах тоже считаются от ширины.
  • max-width + margin-inline: auto — базовый адаптивный контейнер; min-height безопаснее фиксированной height.
  • 100vw включает полосу прокрутки, для мобильного первого экрана есть dvh; ширину по содержимому дают fit-content, min-content, max-content.

Где применяется / связь с практикой

Освойте тему на практике

Размеры блоков — первое, с чем сталкивается верстальщик: адаптивный контейнер, карточки товаров, колонки, первый экран лендинга. Ошибки здесь дают самые заметные дефекты — горизонтальный скролл на телефоне, наезжающий текст, «разъехавшуюся» сетку. Системно разобрать блочную модель, flex, grid и адаптивную верстку на практических макетах можно на курсе «HTML/CSS». Разборы отдельных тем фронтенда с преподавателями проходят на открытых уроках Otus.

FAQ

Чем width: 100% отличается от width: auto?
auto занимает всю доступную ширину с учетом padding, border и margin, поэтому блок не вылезает за родителя. 100% приравнивает к ширине родителя саму width, и в режиме content-box отступы и рамка добавляются сверху.

Можно ли задавать размеры в em и rem?
Да. rem считается от размера шрифта корневого элемента (обычно 16px), em — от размера шрифта самого элемента. Ширину текстовых блоков удобно ограничивать в ch или rem, например max-width: 65ch, — тогда длина строки остается читаемой при любом шрифте.

Почему margin-inline: auto не центрирует блок?
Центрирование работает только у блока с шириной меньше родителя: нужен width или max-width. Блок с width: auto уже занимает всю строку, и свободного места для автоматических отступов нет.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)