причина
Проблема в том, что плавающие элементы находятся вне потока :
Элемент вызывается вне потока, если он является плавающим, абсолютно позиционированным или является корневым элементом.
Следовательно, они не влияют на окружающие элементы, как элемент, находящийся в потоке .
Это объясняется в 9.5 Float :
Поскольку поплавок не находится в потоке, непозиционированные блоки блоков, созданные до и после блока поплавка, перемещаются вертикально, как если бы поплавок не существовал. Тем не менее, текущий и последующие линейные блоки, созданные рядом с плавающей точкой, сокращаются по мере необходимости, чтобы освободить место для поля поля с плавающей точкой.
html {
width: 550px;
border: 1px solid;
}
body {
font-family: sans-serif;
color: rgba(0,0,0,.15);
}
body:after {
content: '';
display: block;
clear: both;
}
div {
position: relative;
}
div:after {
font-size: 200%;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: center;
}
.block-sibling {
border: 3px solid green;
}
.block-sibling:after {
content: 'Block sibling';
color: green;
}
.float {
float: left;
border: 3px solid red;
height: 90px;
width: 150px;
z-index: 1;
}
.float:after {
content: 'Float';
color: red;
}
<div class="float"></div>
<div class="block-sibling">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor.
</div>
Это также указано в 10.6 Расчет высоты и полей . Для «нормальных» блоков ,
Учитываются только дочерние элементы в нормальном потоке (т.е. плавающие блоки и абсолютно позиционированные блоки игнорируются […])
html {
width: 550px;
border: 1px solid;
}
body {
font-family: sans-serif;
color: rgba(0,0,0,.15);
}
body:after {
content: '';
display: block;
clear: both;
}
div {
position: relative;
}
div:after {
font-size: 200%;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: center;
}
.block-parent {
border: 3px solid blue;
}
.block-parent:after {
content: 'Block parent';
color: blue;
}
.float {
float: left;
border: 3px solid red;
height: 130px;
width: 150px;
}
.float:after {
content: 'Float';
color: red;
}
<div class="block-parent">
<div class="float"></div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
</div>
Хакерское решение: оформление
Способ решения этой проблемы - принудительное размещение некоторого элемента в потоке под всеми поплавками. Затем высота родительского элемента будет увеличиваться, чтобы обернуть этот элемент (и, следовательно, также плавать).
Это может быть достигнуто с помощьюclear
свойства :
Это свойство указывает, какие стороны блока (ов) элемента могут не
быть смежными с более ранним плавающим блоком.
html {
width: 550px;
border: 1px solid;
}
body {
font-family: sans-serif;
color: rgba(0,0,0,.15);
}
body:after {
content: '';
display: block;
clear: both;
}
div {
position: relative;
}
div:after {
font-size: 200%;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: center;
}
.block-parent {
border: 3px solid blue;
}
.block-parent:after {
content: 'Block parent';
color: blue;
}
.float {
float: left;
border: 3px solid red;
height: 84px;
width: 150px;
}
.float:after {
content: 'Float';
color: red;
}
.clear {
clear: both;
text-align: center;
height: 37px;
border: 3px dashed pink;
}
.clear:after {
position: static;
content: 'Block sibling with clearance';
color: pink;
}
<div class="block-parent">
<div class="float"></div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra.
<div class="clear"></div>
</div>
Таким образом, решение заключается в добавлении пустого элемента с clear: both
последним братом поплавков
<div style="clear: both"></div>
Однако это не семантика. Так что лучше сгенерировать псевдоэлемент в конце родительского :
.clearfix::after {
clear: both;
display: block;
}
Существует несколько вариантов этого подхода, например, использование устаревшего синтаксиса :after
с одной двоеточием для поддержки старых браузеров или использование других дисплеев на уровне блоков, например display: table
.
Решение: корни BFC
Существует исключение из проблемного поведения, определенного в начале: если блочный элемент устанавливает контекст форматирования блока (является корнем BFC), то он также переносит свое плавающее содержимое.
Согласно 10.6.7 «Авто» высоты для блочного форматирования корней контекста ,
Если у элемента есть плавающие потомки, нижний край поля которых находится ниже нижнего края содержимого элемента, то высота увеличивается, чтобы включить эти края.
html {
width: 550px;
border: 1px solid;
}
body {
font-family: sans-serif;
color: rgba(0,0,0,.15);
}
body:after {
content: '';
display: block;
clear: both;
}
div {
position: relative;
}
div:after {
font-size: 200%;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: center;
}
.block-parent {
border: 3px solid blue;
}
.block-parent.bfc-root:after {
content: 'BFC parent';
color: blue;
}
.float {
float: left;
border: 3px solid red;
height: 127px;
width: 150px;
}
.float:after {
content: 'Float';
color: red;
}
.bfc-root {
overflow: hidden;
}
<div class="block-parent bfc-root">
<div class="float"></div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
</div>
Кроме того, как объяснено 9.5 Поплавки , корни BFC также полезны из-за следующего:
Граничный блок таблицы, замененный элемент уровня блока или элемент в обычном потоке, который устанавливает новый контекст форматирования блока […], не должен перекрывать поле полей любых чисел в том же контексте форматирования блока, что и сам элемент ,
html {
width: 550px;
border: 1px solid;
}
body {
font-family: sans-serif;
color: rgba(0,0,0,.15);
}
body:after {
content: '';
display: block;
clear: both;
}
div {
position: relative;
}
div:after {
font-size: 200%;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: center;
}
.block-sibling {
border: 3px solid green;
}
.block-sibling.bfc-root:after {
content: 'BFC sibling';
color: green;
}
.float {
float: left;
border: 3px solid red;
height: 90px;
width: 150px;
z-index: 1;
}
.float:after {
content: 'Float';
color: red;
}
.bfc-root {
overflow: hidden;
}
<div class="float"></div>
<div class="block-sibling bfc-root">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.
</div>
Контекст форматирования блока устанавливается
Блокировать коробки с, overflow
кроме visible
, например,hidden
.bfc-root {
overflow: hidden;
/* display: block; */
}
Блокировать контейнеры, которые не являются блок-блоками: когда display
установлено значение inline-block
, table-cell
или table-caption
.
.bfc-root {
display: inline-block;
}
Плавающие элементы: когда float
установлено в left
или right
.
.bfc-root {
float: left;
}
Абсолютно позиционированные элементы: когда position
установлено на absolute
или fixed
.
.bfc-root {
position: absolute;
}
Обратите внимание, что они могут иметь нежелательные побочные эффекты, такие как отсечение переполнения содержимого, вычисление автоматической ширины с помощью алгоритма сжатия по размеру или выход из потока. Таким образом, проблема в том, что невозможно иметь элемент уровня блока в потоке с видимым переполнением, который устанавливает BFC.
Дисплей L3 решает эти проблемы:
Созданы flow
и внутренние типы отображения, чтобы лучше выразить типы отображения макета потока и создать явный переключатель для превращения элемента в корень BFC . (Это должно устранить необходимость в таких хакерах, как и […])flow-root
::after { clear: both; }
overflow: hidden
К сожалению, пока нет поддержки браузера. В конце концов мы сможем использовать
.bfc-root {
display: flow-root;
}