Как работает box-sizing в CSS: content-box и border-box

box-sizing определяет, что именно входит в заданные width и height элемента. По умолчанию (content-box) они относятся только к содержимому, а padding и border добавляются сверх них - поэтому элемент часто получается шире, чем задано. Значение border-box заставляет width и height включать padding и border, так что итоговый размер остаётся именно таким, каким его задали.

Попробуй прямо сейчас: удали строку box-sizing: border-box; - блок станет заметно шире 200px, потому что вернётся расчёт content-box по умолчанию.

Что такое box-sizing: как считается ширина по умолчанию (content-box)

box-sizing: content-box - значение по умолчанию, действует даже если само свойство нигде не написано. При нём width и height относятся только к области содержимого, а padding и border добавляются к ней снаружи. Поэтому реальная (видимая) ширина элемента равна width + padding с двух сторон + border с двух сторон - и почти всегда оказывается больше того числа, что написано в width.

width: 200px; padding: 20px; border: 5px solid; (content-box) - реальная ширина получится 250px (200+20+20+5+5), а не 200px.

Ожидание, что элемент с width: 200px всегда займёт ровно 200px места - при content-box это верно только если padding и border равны нулю.

Как border-box меняет расчёт ширины и высоты

box-sizing: border-box переворачивает расчёт: теперь width и height - это итоговый, видимый размер элемента, включающий и padding, и border. Сама область содержимого при этом сжимается: content = width - padding с двух сторон - border с двух сторон. Margin в этот расчёт не входит никогда, ни при content-box, ни при border-box - отступ снаружи элемента всегда добавляется дополнительно.

box-sizing: border-box; width: 200px; padding: 20px; border: 5px solid; - реальная ширина остаётся ровно 200px, а не 250px.

Ставят border-box и ждут, что margin тоже "впишется" в width - margin по-прежнему добавляется снаружи, box-sizing на него не влияет вообще.

Почему box-sizing не наследуется и как включить border-box для всех элементов

box-sizing - это НЕ наследуемое свойство: если поставить его на body или на родительский блок, дочерние элементы это не почувствуют и останутся на content-box по умолчанию. Поэтому на практике box-sizing: border-box почти всегда ставят сразу на все элементы через универсальный селектор * (иногда вместе с *::before и *::after) - это и убирает частую причину "поломанной" вёрстки: при content-box колонка шириной 50% с padding в px реально становится ШИРЕ 50%, а с border-box padding поглощается внутри тех же 50%.

* { box-sizing: border-box; } - стандартный сброс, применяется одинаково ко всем элементам сразу, наследование тут ни при чём.

body { box-sizing: border-box; }, в расчёте что подействует на все элементы страницы - не подействует, потому что свойство не наследуется.

Из истории Термин box-sizing с теми же значениями content-box и border-box уже встречается в черновике спецификации CSS3 Box Model от 26 июля 2001 года - причём сам черновик описывает border-box как фиксацию поведения width и height, которое некоторые старые браузеры и так неявно применяли к заменяемым элементам и полям ввода. Несмотря на такую раннюю формулировку, свойство ещё долго было доступно в браузерах только с вендорными префиксами, прежде чем стало обычным CSS-свойством без приставок.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Задают width в процентах и padding в px при content-box (по умолчанию) Итоговая ширина получается больше заданного процента, колонки не помещаются в ряд Поставить box-sizing: border-box - padding войдёт в процент, а не добавится сверху
Ставят box-sizing: border-box на body или на родителя, рассчитывая на наследование Дочерние элементы остаются на content-box - свойство не наследуется Ставить через универсальный селектор * (или явный приём html + *{box-sizing:inherit})
Применяют border-box только к части элементов макета В одной вёрстке одновременно два разных способа расчёта ширины - легко запутаться Ставить сброс сразу на весь документ через *, а не выборочно
Считают, что border-box "втягивает" в width ещё и margin Реальные внешние отступы больше, чем ожидалось при раскладке Помнить, что margin всегда остаётся снаружи, box-sizing на него не влияет

Шпаргалка

Что нужноКак сделать
Значение по умолчаниюbox-sizing: content-box;
Ширина = только содержимоеcontent-box (padding и border добавляются сверх width)
Ширина = итоговый видимый размерborder-box (padding и border входят в width)
Формула реальной ширины (content-box)width + padding*2 + border*2
Формула реальной ширины (border-box)ровно width (содержимое = width - padding*2 - border*2)
Сбросить на все элементы разом* { box-sizing: border-box; }

Коротко: отвечаем на вопросы

Ставить box-sizing: border-box через * для всех элементов сразу - это нормально?

Да, это широко принятая, стандартная практика - так делают в Bootstrap и множестве других реальных проектов, и все современные браузеры это поддерживают. Единственная оговорка возникает в компонентных подходах, где глобальный сброс иногда сознательно переопределяют локально под конкретный компонент, но само по себе применение border-box ко всем элементам безопасно.

Если поставить box-sizing: border-box на body, подействует ли это на все элементы страницы?

Нет. box-sizing не наследуется по умолчанию, поэтому дочерние элементы body всё равно останутся на content-box. Из-за этого box-sizing обычно ставят через универсальный селектор *, либо используют приём html { box-sizing: border-box; } вместе с *, *::before, *::after { box-sizing: inherit; }, который сначала явно передаёт значение по наследованию, а затем позволяет переопределить его для отдельного компонента.

Категория
css
Поделиться в социальных сетях

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

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×