box-sizing (читается «бокс-сайз») — CSS-свойство, определяющее способ подсчёта браузером итоговых размеров блочного элемента. На практике существуют два основных значения, полностью исключающие друг друга: content-box и border-box
- Значения свойства box-sizing
- Как задаётся значение свойства box-sizing
- Наследование свойства box-sizing
- Паттерн: Наследование через корень
- Паттерн: Прямое назначение
- «Авторитетное сравнение»
- Как это работает
- Быстрый фикс-fallback
Значения свойства box-sizing
- content-box
- Значение «box-sizing» по умолчанию. Мерим внутреннее содержимое блока (content), без учета отступов и рамок-бордеров:
«Размер блока» = content. - border-box
- Складываем размеры: содержимое (content) + внутренние отступы (padding) + толщина рамки (border).
«Размер блока» = content + padding + border.
border-box, популярное ныне значение свойства box-sizing — учитывает размеры блока по внешнему краю элемента
Как задаётся значение свойства box-sizing
- Явно и непосредственно, в CSS-свойстве элемента: content-box или border-box
- Наследование от родителя: inherit
- Сброс к начальному значению: initial (вернёт значение по умолчанию: box-sizing: content-box;)
Наследование свойства box-sizing
- По умолчанию: Свойство box-sizing не наследуется
- Явное наследование: box-sizing: inherit; — наследует значение родителя при явном указании box-sizing: inherit; в дочернем элементе и создает цепочку наследования с исключительно переопределяемыми свойствами. См. «Быстрый фикс-fallback»
Особенности наследования.
Включение наследования необратимо. Включенное однажды наследование свойства box-sizing: inherit; нельзя остановить или отменить. Наследование действует по цепочке вниз и НЕ! прекращается никогда. Доступно лишь переопределение (изменение) значения свойства для потомков. Механизм inherit не отключается. В CSS нет правила или команды, которая отключает наследование box-sizing: inherit;, как, например, text-decoration: none;
Паттерн: Наследование через корень
Популярный способ глобальной установки box-sizing получил название «Паттерн: Наследование через корень» и реализует каскадную CSS-логику: задаём box-sizing: border-box на корневой элемент html и inherit-распространяем значение на все элементы, включая псевдоэлементы.
/* Паттерн: Наследование через корень [inheritance-based] */
html {
/* Задаём корню (корневому элементу)
стартовое базовое значение */
box-sizing: border-box;
}
/* Устанавливаем наследование «от корня» */
*, *::before, *::after {
margin : 0;
padding : 0;
/* Элемент всегда берёт значение
box-sizing у своего родителя */
box-sizing : inherit;
}
/* • Все элементы наследуют box-sizing от корня html
(в нашем случае: border-box).
•• Если элементу ниже по тексту явно задать content-box,
это значение БУДЕТ! наследоваться всеми его потомками
до нового явного изменения (переназначения).
••• Так работает вторая строка нашего кода:
*, *::before, *::after { box-sizing: inherit; } */
Прим. Указание [margin:0;padding:0;] — не имеет никакого отношения к нашей теме и указано, исключительно, чтобы «не портить глаза»
Паттерн: Прямое назначение
Паттерн: «Прямое назначение» — не менее популярен и часто (если не всегда) используется в небольших проектах. Смысл его предельно ясен: никакого наследования и прямая установка box-sizing каждому элементу.
/* Паттерн: Прямое назначение [direct assignment] */
*, *::before, *::after {
margin : 0;
padding : 0;
/* Задаем сразу всем и конкретно каждому элементу,
явно, напрямую и без всякого наследования */
box-sizing : border-box;
}
/* • Все элементы получают box-sizing явно и напрямую
(в нашем случае — border-box).
•• Если НИЖЕ, в коде CSS, элементу ЯВНО задать content-box, значение
<strong>НЕ БУДЕТ! наследоваться</strong> потомками,
потому как, для всех элементов применяется глобальное правило:
*, *::before, *::after { box-sizing: border-box; }
••• За сим, значения, отличные от заданного нами базового
прямого назначения (box-sizing:border-box;),
при необходимости — задаем постоянно, явно и снова, каждому элементу. */
«Авторитетное сравнение»
Паттерны «Наследование через корень» и «Прямое назначение» — полностью рабочие блоки кода глобальной установки свойства box-sizing, широко применяемые в современной верстке.
Оба варианта — нормальные и рабочие, делают одно и то же, но — по-разному:
- Наследование через корень
(inheritance-based) - Гибкий и удобный вариант, если нужно локально менять box-sizing с наследованием: менять поведение в отдельных местах-цепочках, пачкой, для всех вложенных элементов.
- Принцип работы: изменил значение у элемента-родителя → значение пошло от родителя вниз, ко всем вложенным дочерним элементам, пока не задали новое значение box-sizing (не переопределили).
- Прямое назначение
(direct assignment) - Проще и жёстче возни с наследованием. Подходит для большинства проектов без особых требований. Значение box-sizing элемента-родителя не наследуется вниз, к потомкам, и действует исключительно для указанного элемента. Если нужно то же самое у других элементов, включая дочерние — задаёшь каждому отдельно.
- Принцип работы: «изменил здесь — здесь все и закончилось». Надо переопределить базу пять раз под ряд — задавай пять раз под ряд. Наследования нет, свойство не передается вниз.
Главное принципиальное отличие рассматриваемых вариантов: наследование свойства box-sizing по дереву DOM:
- Вариант 1: наследуется, передаёт значение потомкам (значение идёт вниз по элементам).
- Вариант 2: не наследуется, не передаёт значение потомкам — действует для текущего элемента (значение остаётся там, где задано).
Как это работает
Вариант 1 [inheritance-based] (наследование)
- Базовое значение box-sizing задано в корне html и наследуется потомками, т.е. передаётся ко всем вложенным (дочерним) элементам.
- Переопределенное значение box-sizing ведет себя точно так же.
- Создаются цепочки наследования: от родителя к дочернему элементу.
Вариант 2 [direct assignment] (напрямую)
- Базовое значение box-sizing задаётся сразу каждому элементу, оно никуда не передаётся и не наследуется.
- Каждый элемент живёт «сам по себе».
- Значение не передаётся вниз по DOM и не создаются цепочки: от родителя к дочернему элементу.
В итоге, общая картина отличия:
- Вариант 1: значение задано родителю и «течёт вниз» к дочерним элементам.
- Вариант 2: значение задаётся каждому отдельно и остаётся на месте. Вложенные элементы никак на него не реагируют.
Архивные авторские тексты
От Автора: Статья сконструированна из чатовых текстов, накопившихся в процессе технической переписки.
Вариант 1 [inheritance-based]:
- Наследование свойства есть.
- Наследование задано глобально, в строке:
*, *::before, *::after { box-sizing: border-box; } - Создаются цепочки наследования от родителя к потомку (дочернему элементу).
- Значение box-sizing задаётся в корне html и наследуется: дочерний элемент берёт текущее значение у своего родителя через inherit, заданный глобально.
- Значение передаётся вниз по дереву.
Вариант 2 [direct assignment]:
- Наследования свойства нет.
- Цепочек наследования не существует.
- Значение box-sizing задаётся сразу всем элементам индивидуально, напрямую через глобальный селектор
- и псевдоэлементы
*::before, *::after.
Практика (как это работает)
Разница между вариантами проявляется не просто в наличии/отсутствии механизма наследования, а в том, что происходит, если изменить box-sizing внутри дерева:
Вариант 1 [inheritance-based]
- Есть цепочка наследования.
- Если где-то в дереве задать:
box-sizing: content-box;, то это значение становится новым для этого элемента и автоматически передаётся всем его потомкам. - Актуальное значение у родителя может меняться сколько угодно раз, и каждый раз становится новым источником вниз по дереву.
- Значение можно снова переопределять на любом уровне, и каждый раз оно будет дальше идти вниз по дереву.
- Получается слоистый пирог: каждый раз заданное свойство наследуется до тех пор, пока не будет задано иное.
Девиз: «изменил здесь → пошло дальше вниз, пока снова не переопределили».
Вариант 2 [direct assignment]
- Нет цепочки наследования.
- Если где-то в дереве задать:
box-sizing: content-box;, то это значение влияет только на этот элемент, и потомки не получают это значение. - Потому что для них снова применяется глобальное правило:
*, *::before, *::after { box-sizing: border-box; }
Девиз: «изменил здесь — здесь все и закончилось».
Быстрый фикс-fallback
Быстрый фикс/fallback — личный «зелёный коридор» в проекте для локального исправления поведения CSS без глобальных изменений.
Создаем индивидуальную цепочку наследования, не зависимую от остального кода CSS: задаём box-sizing родителю, а дочернему элементу говорим унаследовать значение (inherit).
селектор родителя { box-sizing: border-box;}
селектор дочернего элемента {box-sizing : inherit; }
Именно этим объясняется тот факт, что в командной разработке, изначально — чаще используется способ [inheritance-based]. Цепочки наследования позволяют легко управлять стилями на уровне компонентов.