Четыре слоя каждого блока
Каждый элемент страницы рисуется прямоугольником из четырех слоев, изнутри наружу:
- Content: текст, изображение или дочерние элементы, размер задают
widthиheight. - Padding: внутренний отступ между содержимым и рамкой. На нем виден фон элемента.
- Border: линия вокруг padding.
- Margin: внешний отступ за рамкой, который отталкивает другие блоки. Всегда прозрачный.
В примере у каждого слоя свой цвет: синее содержимое, зеленый padding, темная рамка и янтарная область вокруг блока, это margin (ее рисует обертка, ведь сам margin прозрачен).
Строку под блоком измеряет браузер: 160 + 20 + 20 + 10 + 10 = 220px. Margin добавляет еще по 24px с каждой стороны, но он снаружи блока, поэтому в эти 220 не входит.
Расчет ширины: content-box и border-box
По умолчанию (box-sizing: content-box) width задает только содержимое. Padding и border добавляются сверху, и блок получается шире написанного числа. С box-sizing: border-box width это весь блок, а содержимое сжимается, чтобы вместить padding и border.
content-box (по умолчанию) | border-box | |
|---|---|---|
width означает | Содержимое | Содержимое + padding + border |
width: 200px; padding: 20px; border: 5px | 250px в ширину | 200px в ширину |
| Область содержимого в этом случае | 200px | 150px |
| Margin | Снаружи, не учитывается | Снаружи, не учитывается |
Сброс border-box
Раз с border-box размеры складываются предсказуемо, почти каждая современная таблица стилей начинается с этого правила:
*,
*::before,
*::after {
box-sizing: border-box;
}
Сильнее всего это заметно с процентами. Две колонки width: 50% с padding не помещаются в одну строку при content-box, потому что каждая равна 50% плюс ее padding:
(HTML-комментарии убирают пробел между колонками inline-block, который иначе добавил бы несколько пикселей.)
Блочная модель в DevTools
Каждый браузер рисует блочную модель за вас. Кликните по элементу правой кнопкой, выберите Inspect (Просмотреть код) и откройте вкладку Computed (Layout в Firefox): схема показывает размер содержимого в центре, а вокруг значения padding, border и margin. Наведение на элемент в панели Elements тоже подкрашивает страницу: содержимое синим, padding зеленым, margin оранжевым.
Строчные блоки подчиняются другим правилам
Описанная выше блочная модель относится к блочным элементам вроде <div> и <p>. Строчные элементы вроде <span>, <a> и <strong> переносятся внутри строки текста и по-другому обращаются с вертикальным пространством:
| Свойство | У строчного элемента |
|---|---|
width, height | Игнорируются |
| Горизонтальные padding, border, margin | Применяются и раздвигают соседей в стороны |
| Вертикальные padding и border | Рисуются, но не отодвигают строки сверху и снизу |
| Вертикальный margin | Игнорируется |
display: inline-block дает элементу внутри строки полную блочную модель: его ширина, высота, padding и margin занимают место. Каждый слой подробно разобран в разделах padding в CSS и margin в CSS.
Частые ошибки
- Добавили padding блоку с фиксированной шириной, и он вырос. При
content-boxpadding и border прибавляются кwidth. Используйтеborder-box. - Ожидание, что margin примет цвет фона. Margin всегда прозрачен; для цветного пространства используйте padding.
heightили вертикальный margin у строчного элемента. Ничего не происходит; используйтеdisplay: inline-blockилиblock.- Забытые рамки в расчете. Рамка 1px у элемента с
width: 100%делает его на 2px шире приcontent-box, и может появиться горизонтальная прокрутка. - Путаница margin и padding. Коротко: padding внутри рамки, margin снаружи. На странице margin и padding: разница они сравниваются рядом.
Часто задаваемые вопросы
Что такое блочная модель CSS?
Правило, по которому каждый элемент отображается прямоугольным блоком из четырех слоев: содержимое, padding вокруг него, border вокруг padding и margin снаружи от border. Ширина, высота и отступы в CSS задаются именно на этих слоях.
Что делает box-sizing: border-box?
Включает padding и border в width и height. Блок с width: 200px, padding: 20px и рамкой 5px тогда ровно 200px в ширину, а область содержимого сжимается до 150px. Значение по умолчанию, content-box, добавляет padding и border сверху, и получается 250px.
Как считается полная ширина элемента?
С content-box по умолчанию: width + левый и правый padding + левый и правый border. С border-box: только width. Margin в обоих случаях снаружи блока, поэтому он добавляется к месту, которое занимает элемент, а не к его собственной ширине.
Входит ли margin в блочную модель?
Да, это самый внешний слой, но он всегда прозрачный и никогда не входит в собственную ширину элемента и его фон. Он только отталкивает соседние блоки.
Стоит ли задавать box-sizing: border-box всем элементам?
Большинство проектов так и делают, правилом *, *::before, *::after { box-sizing: border-box; } в начале таблицы стилей. С ним ширины в процентах и padding складываются так, как люди ожидают, а фреймворки вроде Bootstrap и Tailwind содержат тот же сброс.