- PVSM.RU - https://www.pvsm.ru -

Очистка float-элементов посредством создания нового блочного контекста форматирования

В данной статье рассматривается ситуация, когда элемент, создающий новый блочный контекст форматирования, имеет потомков, имеющих значение свойства float отличное от none. В большинстве статей на данную тему поведение элементов в подобных случаях предлагается принять на веру, поэтому в данной статье акцент делается на обосновании интерпретации браузерами положений спецификации W3C.

Задача

Существует некий элемент-контейнер, в котором находится элемент со значением свойства float, установленным как left. Для наглядности у контейнера установлены границы и фон.

Очистка float элементов посредством создания нового блочного контекста форматирования
jsFiddle [1]

Как видно из примера, контейнер схлопывается — его рассчитанная высота устанавливается в ноль. Этот случай часто встречается в верстке, все к нему привыкли и сложно найти верстальщика, не сталкивавшегося с такой ситуацией.

Почему так происходит?

Дело в том, что если значение свойства height незамещаемого блочного элемента (т.е. контейнера в нашем примере) установлено в auto (а это значение установлено по умолчанию), то его высота определяется исходя из высоты элементов-потомков; при этом в расчет берутся только элементы, участвующие в нормальном потоке. Таким образом, float-элементы и элементы, спозиционированные абсолютно, игнорируются при определении высоты контейнера (ссылка на спецификацию [2]).

Решение

Существует несколько вариантов решения этой задачи.

Самый очевидный — поместить блок с соответствующим значением свойства clear после float-элемента. В этом случае блок находится ниже float-элемента по определению свойства clear, а контейнер рассчитывает высоту исходя из положения этого элемента.

Более продвинутым (и, возможно, лучшим из всех) решением является внедрение класса clearfix, популяризованного уже не твиттеровским Bootstrap’ом и позволяющего добиться того же эффекта без нарушения семантики документа.
Но есть еще одно решение. Оно состоит в том, чтобы задать контейнеру overflow:hidden.

Очистка float элементов посредством создания нового блочного контекста форматирования
jsFiddle [3]

В самом деле, все становится на свои места, контейнер принимает высоту внутреннего элемента, но как это работает?

Объяснение

Прежде чем рассмотреть механизм данного явления, отметим, что не только overflow:hidden решает проблему. Контейнер примет высоту float-элемента, если ему задать абсолютную позицию, установить display: inline-block и в некоторых других случаях. Что же происходит на самом деле?

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

Очистка float элементов посредством создания нового блочного контекста форматирования

Если вернуться к верстке, то блочный контекст форматирования — среда, в которой блоки размещаются в привычном для блоков порядке — сверху вниз, расстояние между ними определяется отступами (margins), отступы соседних блоков схлопываются (ссылка на спецификацию [4]). Элементы из разных блочных контекстов форматирования никак не могут повлиять на положение друг друга на странице.

Если вы впервые сталкиваетесь с понятием блочного контекста форматирования, попробуйте решить следующую практическую задачу: jsFiddle [5].

Итак, с понятием контекста разобрались. Теперь ответим на следующий вопрос — почему при создании блочного контекста форматирования float-элементы учитываются для определения высоты контейнера?

Дело в том, что этот случай отдельно оговорен в спецификации. К блокам, создающим новый блочный контекст форматирования и имеющим height:auto (напомню еще раз, что это значение установлено по умолчанию), применяется следующее правило (ссылка на спецификацию [6]):

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

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

Когда создается новый блочный контекст форматирования

В этой главе перечислены случаи, в которых создается новый контекст форматирования. В контексте проблематики данной статьи этот перечень — список случаев, при которых блок будет подстраиваться по высоте под дочерние float-элементы. Итак, блочный контекст форматирования создается:

  • float-элементами;
  • абсолютно спозиционированными элементами;
  • фиксированными элементами (т.к. position:fixed — разновидность абсолютного позиционирования, ссылка на спецификацию [7]);
  • элементами, представляющими собой блочный контейнер внутри, но имеющими другую структуру снаружи (такие как inline-block, table-cell, table-caption);
  • блоками с overflow установленным в любое значение, кроме visible;
  • элементом fieldset (в большинстве браузеров).

Итого

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

Автор: everyonesdesign

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/web-razrabotka/30545

Ссылки в тексте:

[1] jsFiddle: http://jsfiddle.net/C7Kzm/1/

[2] ссылка на спецификацию: http://www.w3.org/TR/CSS2/visudet.html#normal-block

[3] jsFiddle: http://jsfiddle.net/C7Kzm/2/

[4] ссылка на спецификацию: http://www.w3.org/TR/CSS2/visuren.html#block-formatting

[5] jsFiddle: http://jsfiddle.net/sz95k/2/

[6] ссылка на спецификацию: http://www.w3.org/TR/CSS21/visudet.html#root-height

[7] ссылка на спецификацию: http://www.w3.org/TR/CSS2/visuren.html#fixed-positioning

[8] Источник: http://habrahabr.ru/post/174443/