Блочный контекст форматирования

Описание

Блочный контекст форматирования — часть механизма отображения веб-страницы в CSS. Это та область, в которой происходит расположение блочных элементов, и в котором плавающие элементы взаимодействуют с другими элементами.

Блочный контекст форматирования создаёт один из следующих способов (методов):

  • корневой элемент документа (<html>).
  • плавающие элементы (элементы, у которых float не равно none)
  • абсолютно позиционированные элементы (элементы, значение position которых либо absolute, либо fixed)
  • «строчные блоки» (элементы с display: inline-block)
  • ячейки таблицы (элементы с display: table-cell, являющимся значением по умолчанию для ячеек таблицы в HTML)
  • заголовки таблицы (элементы с display: table-caption, являющимся значением по умолчанию для заголовков таблицы в HTML)
  • анонимные ячейки таблицы, неявно создаваемые элементами с display: table, table-row, table-row-group, table-header-group, table-footer-group (значения по умолчанию для таблиц, строк таблиц, «шапок», «подвалов» и тел таблиц в HTML соответственно) либо inline-table
  • элементы, у которых значение свойства overflow отличается от visible
  • display: flow-root
  • элементы с contain (en-US): layout, content или strict
  • флекс-элементы (непосредственные потомки элемента с display: flex или inline-flex)
  • грид-элементы (непосредственные потомки элемента с display: grid или inline-grid)
  • многоколоночные контейнеры (элементы, у которых column-count или column-width (en-US) не равно auto, включая элементы с column-count: 1)
  • column-span (en-US): all должно всегда создавать новый блочный контекст форматирования, даже если элемент с column-span: all не находится в многоколоночном контейнере (изменение в спецификации, баг Chrome).

Блочный контекст форматирования применяется ко всему содержимому того элемента, который его создал.

Блочные контексты форматирования важны для размещения плавающих элементов (см. float) и отмены их обтекания (см.clear) . Правила размещения плавающих элементов и сброса обтекания применяются только к элементам внутри одного и того же блочного контекста форматирования. Плавающие элементы не влияют на размещение содержимого внутри других блочных контекстов форматирования, и отмена обтекания распространяется только на плавающие элементы из того же самого контекста форматирования. Схлопывание внешних отступов тоже происходит только между блоками из одного и того же блочного контекста форматирования.

Примеры

Как сделать плавающему контенту и соседнему с ним контенту одинаковую высоту

Давайте рассмотрим пару примеров, чтобы рассмотреть эффект от создания нового блочного контекста форматирования.

В примере ниже мы имеем плавающий элемент внутри <div> с заданным border. Содержимое этого <div> обтекает плавающий элемент. Так как содержимое float выше, чем остальное содержимое, обтекающее его, border элемента div теперь проходит сквозь float. Как объясняется в руководстве In Flow and Out of Flow (en-US), плавающий элемент был исключён из потока элементов, так что фон и граница div включает только его содержимое, но не элемент float.

Использование overflow: auto;

Создадим новый блочный контекст форматирования, который будет содержать в себе плавающий элемент. Раньше обычным способом сделать это было установить overflow: auto или другое значение, отличное от значения по умолчанию overflow: visible.

Задание overflow: auto создало новый блочный контекст форматирования, включающий float. Теперь div стал мини-слоем внутри нашего слоя. Любые дочерние элементы войдут в него.

Проблема использования overflow для создания нового блочного контекста форматирования в том, что свойство overflow предназначено для сообщения браузеру как обращаться с переполнением содержимого. Существуют случаи, в которых оно вызовет появление нежелательных скролл-баров или обрезание теней, когда вы используете это свойство только для того, чтобы создать блочный контекст форматирования. Кроме того, оно потенциально делает код менее понятным для следующего разработчика, так как не всегда очевидно, почему использовано overflow в данном случае. Если вы используете этот подход, хорошей идеей будет прокомментировать код, чтобы объяснить это.

Использование display: flow-root

Одно из новых значений свойства display позволяет нам создавать новый блочный контекст форматирования без всяких потенциально проблемных побочных эффектов. Использование display: flow-root как свойство содержащего блока, создаёт новый блочный контекст форматирования.

CSS

css
.box {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
  display: flow-root;
}
.float {
  float: left;
  width: 200px;
  height: 150px;
  background-color: white;
  border: 1px solid black;
  padding: 10px;
}

С помощью display: flow-root; применённом на элементе <div>, всё внутри этого контейнера будет участвовать в едином блочном контексте форматирования этого контейнера, и плавающие элементы не будут торчать из нижней части контейнера.

Задание значения flow-root имеет смысл тогда, когда вы понимаете, что вы создаёте что-то, что будет действовать так же, как действует корневой root элемент (<html> в браузерах) в том плане, что он создаёт новый контекст для компоновки потока внутри него.

Примечание: display: flow-root; не поддерживается в Safari.

Схлопывание границ margin

Создание нового блочного контекста форматирования предотвращает эффект схлопывания границ между двумя соседними div:

HTML

html
<div class="blue"></div>
<div class="red-outer">
  <div class="red-inner">red inner</div>
</div>

CSS

css
.blue,
.red-inner {
  height: 50px;
  margin: 10px 0;
}

.blue {
  background: blue;
}

.red-outer {
  overflow: hidden;
  background: red;
}

Спецификации

Статьи по теме