Блочная модель CSS: почему блок шире, чем вы задали
Вы поставили width: 300px, а блок занимает 342 пикселя и ломает вёрстку. Разбираем, из чего складывается размер элемента и как box-sizing чинит эту боль за одну строку.

Вы задали блоку width: 300px, добавили внутренний отступ и рамку — а в браузере он занимает 342 пикселя и выталкивает соседний элемент на новую строку. Ничего не сломалось: браузер честно посчитал размер по правилам блочной модели. Просто эти правила не совпадают с интуицией. Разберём, из чего на самом деле складывается размер элемента, почему width — это не вся ширина, и как одна строка CSS избавляет от постоянного пересчёта в уме. Материал для тех, кто уже пишет HTML и CSS, но путается в отступах и рамках.
Из чего состоит любой блок
Каждый элемент на странице браузер представляет как прямоугольник, обёрнутый в несколько слоёв. Их четыре, изнутри наружу:
- content — область содержимого: текст, картинка, вложенные элементы. Её размер задают
widthиheight. - padding — внутренний отступ между содержимым и рамкой. Фон элемента заливает и content, и padding.
- border — рамка вокруг padding. Имеет толщину, которую тоже видно и которая занимает место.
- margin — внешний отступ, прозрачное пространство до соседних элементов. Через фон не просвечивает.
Понять это глазами проще всего в браузере. Откройте DevTools (F12 в Chrome или Firefox), выберите элемент — на вкладке Computed внизу нарисована та самая цветная схема со всеми четырьмя слоями и их значениями в пикселях. Это не картинка из учебника, это реальные размеры вашего блока прямо сейчас.
Где прячутся лишние пиксели
Классическая (стандартная) блочная модель считает так: свойство width задаёт ширину только content. Padding, border и margin прибавляются сверху.
/* CSS, поведение по умолчанию */
.card {
width: 300px;
padding: 20px; /* 20px слева + 20px справа */
border: 1px solid #ccc; /* 1px слева + 1px справа */
}
Реальная ширина, которую займёт этот блок на странице:
300 (content) + 20 + 20 (padding) + 1 + 1 (border) = 342px
Margin в эту цифру не входит — он не часть самого блока, а расстояние до соседей. Но на общий занимаемый ряд он тоже влияет.
Свойство width не управляет тем, сколько места займёт блок. Оно управляет только шириной содержимого внутри рамки. Всё остальное браузер прибавляет сам — и именно здесь ломается вёрстка.
Две модели: content-box и border-box
За то, что именно означает width, отвечает свойство box-sizing. У него два основных значения.
| Что задаёте | content-box (по умолчанию) | border-box |
|---|---|---|
width: 300px | ширина content = 300px | ширина content + padding + border = 300px |
| padding: 20px | прибавляется к 300 | отъедается изнутри 300 |
| border: 1px | прибавляется к 300 | отъедается изнутри 300 |
| Итоговая ширина блока | 342px | ровно 300px |
| Content при padding 20 и border 1 | 300px | 258px |
При border-box число, которое вы написали в width, — это и есть итоговая ширина блока. Padding и border вписываются внутрь, ужимая область содержимого. Считать в уголове ничего не нужно: сказали 300 — получили 300.
Почему content-box вообще существует
content-box — исторически стандартное поведение из спецификации CSS. Менять его в самом стандарте нельзя: это сломало бы миллионы старых страниц, которые на него рассчитаны. Поэтому дефолт остался прежним, а border-box дали как опцию, которую вы включаете сами.
Одна строка, которая всё чинит
На практике почти все проекты переводят всю страницу на border-box одним правилом в начале таблицы стилей:
/* Ставится в самом начале CSS-файла */
*,
*::before,
*::after {
box-sizing: border-box;
}
Селектор * применяет правило ко всем элементам, а ::before и ::after — к псевдоэлементам1, чтобы и они считались одинаково. После этого width: 50% для двух блоков рядом действительно даст две колонки по половине, даже если у каждой есть padding и border. Без этого правила два блока по 50% с любым внутренним отступом не влезут в ряд и второй свалится вниз.
Что делать со схлопыванием margin
Отдельная ловушка, которую border-box не решает: вертикальные margin соседних блоков не складываются, а схлопываются — берётся больший из двух. Если у верхнего блока margin-bottom: 30px, а у нижнего margin-top: 20px, между ними будет 30px, а не 50. Это отдельная тема, здесь только помечаем, что так задумано и это не баг.
Как проверить, что всё считается правильно
- Откройте DevTools клавишей F12 и выберите проблемный блок инструментом-стрелкой (иконка курсора в углу панели).
- Найдите вкладку Computed — внизу будет цветная диаграмма блочной модели с числами. Проверьте, совпадает ли внешний размер с тем, что вы ожидали.
- В диаграмме наведите на слой content, padding, border или margin — соответствующая область подсветится прямо на странице. Видно, какой именно слой занимает лишнее место.
- Если внешняя ширина больше заданной — значит, box-sizing остался content-box. Добавьте правило со звёздочкой выше.
Если не получилось
- Блоки всё равно съезжают вниз, хотя вы поставили border-box. Проверьте, что правило со звёздочкой стоит выше остальных стилей и не перебивается более поздним
box-sizing: content-boxу конкретного элемента. В DevTools на вкладке Styles видно, какое правило победило, а какое зачёркнуто. - Между блоками отступ больше, чем сумма margin. Наоборот — меньше суммы. Это схлопывание вертикальных margin, описанное выше. Оно нормальное.
- У инлайн-элемента (
span,a) не работают width и height. Строчные элементы не подчиняются ширине и высоте. Задайте имdisplay: inline-blockилиblock. - Появился горизонтальный скролл на всю страницу. Часто виноват блок с
width: 100%и padding при content-box: 100% + padding больше ширины окна. border-box убирает это. - Фон вылезает за текст сильнее, чем ожидали. Так и должно быть: фон заливает и content, и padding. Уменьшите padding или уберите фон.
Что делать дальше
Поставьте правило box-sizing: border-box со звёздочкой в начало своего CSS раз и навсегда — дальше все размеры будете задавать без пересчёта в уме. Следующий шаг — разобраться, как эти блоки выстраиваются относительно друг друга: за это отвечают Flexbox и Grid. Блочная модель отвечает за размер одного элемента, а раскладка нескольких — уже их задача. Про поведение блоков хорошо описано в разделе Box model на MDN, с интерактивными примерами прямо в браузере.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: The box model — MDN Web Docs, box-sizing — MDN Web Docs
Частые вопросы
Входит ли margin в width элемента?
Что выбрать — content-box или border-box?
Правило со звёздочкой замедлит страницу?
У меня работает по-другому — может, версия браузера старая?
Почему у span не меняется ширина?
Зачем в правиле со звёздочкой ещё ::before и ::after?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.