Причина
Проблема полягає в тому, що плаваючі елементи витікають :
Елемент викликається потоком, якщо він плаває, абсолютно розташований або є кореневим елементом.
Отже, вони не впливають на навколишні елементи, як це було б вхідним елементом.
Це пояснено в 9,5 поплавків :
Оскільки поплавця немає в потоці, нерозміщені блокові коробки, створені до і після поплавкового поля, протікають вертикально, як ніби поплавця не існувало. Однак поточні та наступні поля рядків, створені поруч з поплавком, скорочуються в міру необхідності, щоб звільнити поле для поля поплавця.
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 Floats , коріння 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;
}