CSS: box model и box-sizing
Введение: как коробка с вещами 📦
Представьте коробку: внутри содержимое, вокруг прокладка, потом стенки, а снаружи пространство до другой коробки.
В CSS каждый блок устроен так же.
Если не учитывать эту модель, ширина «вдруг» становится больше ожидаемой, и верстка ломается.
💡 Совет: сначала поймите, как браузер считает размеры блока, и только потом настраивайте сетку.
✅ Вывод:
box model — это база, без которой сложно делать стабильный layout.
Проблема: блоки ломают ширину ❌
Без понимания box model:
- элемент вылезает за контейнер;
- карточки в ряд не помещаются;
- отступы ведут себя неожиданно.
С пониманием модели:
- ширина считается предсказуемо;
- компоненты легко выравниваются;
- адаптивность работает стабильно.
✅ Вывод:
большинство «сломанных» блоков — это ошибка расчёта размеров, а не проблема flex/grid.
Чем помогает и как работает
- объясняет, из каких частей состоит визуальный блок;
- позволяет точно контролировать итоговые размеры;
- снижает количество layout-багов в адаптивной верстке.
Как это работает:
- Браузер считает размер блока через
content + padding + border (+ margin снаружи). - При
content-boxширина относится только к контенту. - При
border-boxширина уже включаетpaddingиborder. - Отступы между элементами управляются через
margin, внутренние поля — черезpadding.
✅ Вывод:
если правильно выбрать
box-sizing и роль отступов, разметка становится предсказуемой.Ключевые термины (простыми словами)
- Box model — модель коробки элемента в CSS.
- Content — внутреннее содержимое блока.
- Padding — внутренний отступ до границы блока.
- Border — рамка элемента.
- Margin — внешний отступ между элементами.
content-box— ширина/высота считаются только для content.border-box— ширина/высота включают padding и border.- Margin collapse — схлопывание вертикальных margin между соседними блоками.
✅ Вывод:
эти термины нужно знать для любой практической работы с layout.
1. Из чего состоит box model
Назначение: понять, из каких частей складывается реальный размер любого блока.
Простыми словами: у каждого элемента есть "слои коробки": контент, внутренний отступ, рамка и внешний отступ.
Для новичка: представьте посылку: товар внутри — это content, пупырка вокруг — padding, картон коробки — border, а расстояние между коробками на складе — margin. Когда понимаете эту аналогию, вся верстка становится намного проще.
Что это значит в цифрах:
- внешняя ширина = content + padding-left + padding-right + border-left + border-right + margin-left + margin-right;
- внешняя высота считается аналогично по вертикали.
Пример:
.card { width: 300px; padding: 16px; border: 2px solid #94a3b8; margin: 20px;}/* В режиме content-box: итог по ширине = 300 + 32 + 4 + 40 = 376px */🔎 Как это происходит на практике:
- В DevTools выбираю элемент и открываю схему Box Model.
- Сверяю по отдельности content, padding, border и margin.
- Проверяю, совпадает ли реальный размер с тем, который я ожидал в макете.
Характеристики:
- ✅ content — зона, где живут текст, картинки, кнопки.
- ✅ padding увеличивает внутренний воздух и зону взаимодействия.
- ✅ border визуально отделяет блок, но тоже участвует в размере.
- ✅ margin создаёт дистанцию между соседними блоками.
❗ Когда использовать:
всегда, когда блок "не влезает", прыгает сетка или непонятно, откуда берётся лишняя ширина/высота.
✅ Вывод:
если считать размер через все слои box model, "магические" баги верстки исчезают.
2. content-box (по умолчанию)
Назначение: понять дефолтное поведение браузера, из-за которого блоки часто "распухают".
Простыми словами: в content-box свойство width задаёт только ширину контента; padding и border добавляются сверху.
Для новичка: если вы написали width: 200px, это не «полная ширина карточки», а только место под текст и картинку. Как только добавите padding и border, блок станет шире 200px, поэтому ряд может внезапно сломаться.
Пример:
.tile { box-sizing: content-box; width: 200px; padding: 20px; border: 2px solid #1e293b;}/* Реальная ширина = 200 + 40 + 4 = 244px */🔎 Как это происходит на практике:
- Делаю карточку шириной 200px.
- Добавляю padding для воздуха и border для визуального контура.
- Получаю неожиданное переполнение ряда, потому что фактическая ширина уже 244px.
Характеристики:
- ✅ Это стандартный режим браузера "из коробки".
- ⚠️ Легко получить горизонтальный скролл или перенос карточек.
- ✅ Подходит, если важно зафиксировать именно ширину контента (редкие случаи).
❗ Когда использовать:
точечно, когда вы осознанно контролируете контентную область и готовы вручную учитывать добавки от padding и border.
✅ Вывод:
content-box полезен для понимания механики, но в боевой верстке часто создаёт лишние риски.
3. border-box (рекомендуется)
Назначение: сделать расчёт размеров предсказуемым для всей системы компонентов.
Простыми словами: при border-box объявленная ширина уже включает и padding, и border; контент автоматически "ужимается" внутрь заданного размера.
Для новичка: здесь width — это уже итоговый наружный размер блока. То есть карточка с width: 320px останется 320px, даже если вы добавили внутренние отступы и рамку. Браузер сам уменьшит внутреннюю область под контент, поэтому сетка не расползается.
Что это даёт на практике:
- вы задали карточке width: 320px и она действительно остаётся 320px снаружи;
- добавили внутренние отступы, но сетка не "поехала";
- проще собирать колонки, где каждый пиксель важен.
Пример:
html { box-sizing: border-box;} *,*::before,*::after { box-sizing: inherit;} .card { width: 320px; padding: 24px; border: 2px solid #8b5cf6;}/* Внешняя ширина = 320px (стабильно) Ширина контента = 320 - 48 - 4 = 268px */🔎 Как это происходит на практике:
- Один раз включаю глобальное правило на весь проект.
- Строю сетку (flex/grid) без ручных поправок "минус padding".
- Проверяю в DevTools: внешние размеры стабильно совпадают с дизайн-значениями.
- В компонентах оперирую понятной логикой: "ширина блока постоянна, внутренний воздух регулируется padding".
Характеристики:
- ✅ Предсказуемая внешняя геометрия компонентов.
- ✅ Меньше переполнений и меньше "костылей" в адаптиве.
- ✅ Проще поддерживать дизайн-систему и повторяемые карточки.
- ⚠️ В legacy-коде после переключения может потребоваться ревизия старых фиксированных размеров.
❗ Когда использовать:
как дефолт проекта почти всегда: лендинги, админки, дашборды, каталоги, любые интерфейсы с карточками и сетками.
✅ Вывод:
border-box — это практический стандарт: меньше сюрпризов, быстрее разработка, стабильнее верстка.
4. Margin vs Padding
Назначение: чётко разделить, где "внутренний воздух" компонента, а где расстояние между компонентами.
Простыми словами:
- padding — пространство внутри блока (между контентом и рамкой);
- margin — расстояние снаружи блока (до соседей).
Для новичка: простое правило: если нужно "дать воздуху тексту внутри карточки" — это padding. Если нужно "отодвинуть одну карточку от другой" — это margin. От этого правила зависит аккуратность всего интерфейса.
Пример:
.card { padding: 16px; /* внутренний воздух */ margin-bottom: 24px;/* интервал до следующей карточки */ border-radius: 12px;}🔎 Как это происходит на практике:
- Если текст "липнет" к краям карточки, увеличиваю padding.
- Если карточки стоят слишком близко друг к другу, регулирую margin.
- Проверяю, что фон карточки покрывает только её саму, а не расстояние между карточками.
Характеристики:
- ✅ padding расширяет кликабельную и фоновую область элемента.
- ✅ margin не красится фоном и не увеличивает зону клика.
- ⚠️ Подмена ролей ломает ритм интерфейса и ощущение аккуратности.
❗ Когда использовать:
padding — для "внутренней ergonomics" компонента; margin — для компоновки компонентов между собой.
✅ Вывод:
правильное разделение margin/padding делает макет читаемым и устойчивым при росте проекта.
5. Схлопывание margin (кратко)
Назначение: понимать, почему вертикальный отступ иногда меньше, чем "по математике".
Простыми словами: два вертикальных margin могут не суммироваться, а схлопнуться в один (обычно берётся больший).
Для новичка: если у верхнего блока снизу 24px, а у нижнего сверху 16px, между ними будет не 40px, а 24px. Это нормальное поведение CSS, а не ошибка браузера.
Где встречается:
- у соседних блочных элементов в нормальном потоке;
- между родителем и первым/последним дочерним блоком;
- чаще всего в колонках текста и секциях.
Пример:
h2 { margin-bottom: 24px; }p { margin-top: 16px; }/* Между ними будет 24px, а не 40px */🔎 Как это происходит на практике:
- Выставляю вертикальные отступы заголовкам и абзацам.
- Визуально вижу интервал меньше ожидаемой суммы.
- Для контроля ритма переношу часть отступа в padding контейнера или создаю новый контекст (display: flow-root, overflow: auto).
- Помню, что в flex и grid схлопывание маргинов не работает.
Характеристики:
- ✅ Влияет только на вертикальные margin в обычном потоке.
- ✅ Не проявляется внутри flex/grid-контейнеров.
- ⚠️ Часто создаёт ощущение "непредсказуемого" spacing у новичков.
❗ Когда использовать:
когда настраиваете типографику, интервалы секций и хотите одинаковый вертикальный ритм без случайных провалов.
✅ Вывод:
зная правило схлопывания, вы управляете вертикальными отступами осознанно, а не подбором "на глаз".
Сравнение: content-box vs border-box
| Режим | Что включает width | Практика |
|---|---|---|
content-box | только content | нужно вручную учитывать padding/border |
border-box | content + padding + border | удобнее и предсказуемее в большинстве UI |
Часто спрашивают на собеседованиях
- Из чего состоит box model?
content,padding,border,margin. - В чём разница между content-box и border-box? В том, что учитывает
width. - Почему border-box часто рекомендуют глобально? Он упрощает расчёт размеров.
- Чем padding отличается от margin? Внутренний vs внешний отступ.
- Что такое схлопывание margin? Когда вертикальные margin сливаются в один.
✅ Вывод:
эти вопросы проверяют понимание основы layout, без которой сложно работать с CSS.
Типичные ошибки
Ошибка 1: Забыт box-sizing
❌ Неправильно: width рассчитан без учёта padding.
✅ Правильно: использовать
border-box глобально.Ошибка 2: Padding вместо margin
❌ Неправильно: ломается внешний ритм блоков.
✅ Правильно: padding внутри, margin между элементами.
Ошибка 3: Фиксированная ширина + padding
❌ Неправильно: блок вылезает за контейнер в
content-box.
✅ Правильно: учитывать режим расчёта или использовать border-box.Ошибка 4: Не учитывается схлопывание margin
❌ Неправильно: «почему отступ меньше, чем ожидалось?»
✅ Правильно: проверять вертикальные margin соседних блоков.
Best Practices
- Включайте глобально
box-sizing: border-box. - Явно разделяйте роли
marginиpadding. - Проверяйте итоговый размер блока в DevTools.
- Держите систему отступов кратной базовому шагу (например 4/8).
- Избегайте случайного переполнения фиксированных блоков.
- Учитывайте схлопывание margin в текстовых секциях.
Заключение
Ключевые мысли
🎯 Box model объясняет итоговый размер элемента.
🎯
border-box обычно даёт более предсказуемую верстку.
🎯 Осознанная работа с margin/padding убирает хаос в интерфейсе.Если правильно настроить модель коробки, layout становится стабильным и управляемым.