Интернетчик » site » CSS: Глобальная установка box-sizing

CSS: Глобальная установка box-sizing

description:

box-sizing (читается «бокс-сайз») — CSS-свойство, определяющее способ подсчёта браузером итоговых размеров блочного элемента. На практике существуют два основных значения, полностью исключающие друг друга: content-box и border-box

  1. Значения свойства box-sizing
  2. Как задаётся значение свойства box-sizing
  3. Наследование свойства box-sizing
  4. Паттерн: Наследование через корень
  5. Паттерн: Прямое назначение
  6. «Авторитетное сравнение»
  7. Как это работает
  8. Быстрый фикс-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]. Цепочки наследования позволяют легко управлять стилями на уровне компонентов.