Почему переполнение: скрытые имеют неожиданный побочный эффект роста в высоту, чтобы содержать плавающие элементы?

Этот вопрос лучше всего объяснить этой скрипкой со следующим HTML:

<div class="outer">
    <div class="inner-left"></div>
    <div class="inner-right"></div>
</div>

CSS

.outer {
    width: 100px;
    border: solid 5px #000;
}
.inner-left {
    float: left;
    height: 200px;
    width: 50px;
    background: #f00;
}
.inner-right {
    float: right;
    height: 200px;
    width: 50px;
    background: #0f0;
}

В принципе, мне интересно, почему overflow: hidden заставляет внешний элемент расти по высоте, охватывая два плавающих элемента?

Ответ 1

Проще говоря, это потому, что блок-блок с overflow, который не является visible (по умолчанию), создает новый блок форматирования.

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

10.6.7 "Авто" высоты для корня контекста форматирования блока

В некоторых случаях (см., например, разделы 10.6.4 и 10.6.6 выше) высота элемента, который устанавливает контекст форматирования блока, вычисляется следующим образом:

[...]

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

Это было не так в исходной спецификации CSS2, но было представлено как изменение в CSS2.1 в ответ на другую (и гораздо более насущную) проблему. Этот ответ содержит объяснения изменений. По этой причине кажется довольно склонным называть его побочным эффектом, хотя изменения были очень преднамеренными.

Также обратите внимание, что это не то же самое, что очистка поплавков (зазор). Очистка поплавков происходит только при использовании свойства clear и перед очисткой предшествующих поплавков:

  • Если у вас есть элемент с clear: both, являющийся родственником внешнего элемента в вашем примере, поплавки будут очищены, но внешний элемент не будет растягиваться.

  • Если у вас есть подобный элемент (или псевдоэлемент) в качестве последнего дочернего элемента внешнего элемента (что делает его следующим собором поплавков), внешний элемент будет растягиваться вниз, чтобы содержать нижнюю край этого элемента и элемент нулевой высоты, который по существу означает самый нижний край поплавков. Этот метод известен как "clearfix", потому что элемент (или псевдоэлемент) не имеет другой цели, кроме того, чтобы заставить внешний элемент содержать поплавки с помощью зазора внутри него.

Ответ 2

Как я объясню это своим ученикам:

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