Powód
Problem polega na tym, że elementy pływające są poza przepływem :
Element jest wywoływany z przepływu, jeśli jest pływający, pozycjonowany absolutnie lub jest elementem głównym.
Dlatego nie wpływają one na otaczające elementy, jak miałby to wpływ element dopływowy .
Jest to wyjaśnione w 9.5 Floats :
Ponieważ liczba zmiennoprzecinkowa nie znajduje się w przepływie, niepozycjonowane pola bloków utworzone przed i za zmiennoprzecinkową pływają pionowo, tak jakby zmiennoprzecinkowa nie istniała. Jednak bieżące i kolejne pola liniowe utworzone obok pływaka są w razie potrzeby skracane, aby zrobić miejsce dla pola marginesu pływaka.
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>
Jest to również określone w 10.6 Obliczanie wysokości i marginesów . Dla „normalnych” klocków ,
Uwzględniane są tylko dzieci w normalnym przepływie (tzn. Pola pływające i pola absolutnie pozycjonowane są ignorowane […])
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>
Hacky rozwiązanie: rozliczenie
Sposobem na rozwiązanie tego problemu jest wymuszenie umieszczenia elementu przepływowego pod wszystkimi pływakami. Następnie wysokość rodzica wzrośnie, aby owinąć ten element (a tym samym również elementy pływające).
Można to osiągnąć za pomocą clear
właściwości :
Ta właściwość wskazuje, które boki pola elementu nie mogą
przylegać do wcześniejszego pola swobodnego.
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>
Rozwiązaniem jest więc dodanie pustego elementu clear: both
jako ostatniego rodzeństwa elementów pływających
<div style="clear: both"></div>
Nie jest to jednak semantyczne. Lepiej więc wygeneruj pseudoelement na końcu elementu nadrzędnego:
.clearfix::after {
clear: both;
display: block;
}
Istnieje wiele wariantów tego podejścia, np. Użycie przestarzałej składni pojedynczego dwukropka :after
do obsługi starych przeglądarek lub użycie innych wyświetlaczy na poziomie bloku, takich jak display: table
.
Rozwiązanie: Korzenie BFC
Istnieje wyjątek od problematycznego zachowania zdefiniowanego na początku: jeśli element bloku ustanawia kontekst formatowania bloku (jest katalogiem głównym BFC), wówczas również zawinie swoją swobodną zawartość.
Zgodnie z 10.6.7 wysokości „Auto” dla kontekstowych katalogów formatowania bloku ,
Jeśli element ma pływających potomków, których dolna krawędź marginesu znajduje się poniżej dolnej krawędzi zawartości elementu, wówczas wysokość jest zwiększana, aby uwzględnić te krawędzie.
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>
Dodatkowo, jak wyjaśniono 9.5 Floats , korzenie BFC są również przydatne z następujących powodów:
Obramowanie tabeli, element zastępowany na poziomie bloku lub element w normalnym przepływie, który ustanawia nowy kontekst formatowania bloku […] nie może nakładać się na pole marginesu dowolnych elementów pływających w tym samym kontekście formatowania bloku, co sam element .
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>
Kontekst formatowania bloku jest tworzony przez
Blokuj skrzynki overflow
innymi niż visible
, nphidden
.bfc-root {
overflow: hidden;
/* display: block; */
}
Blokuj kontenery, które nie są blokami: kiedy display
jest ustawiony na inline-block
, table-cell
lub table-caption
.
.bfc-root {
display: inline-block;
}
Elementy pływające: kiedy float
jest ustawiony na left
lub right
.
.bfc-root {
float: left;
}
Elementy absolutnie pozycjonowane: kiedy position
jest ustawiony na absolute
lub fixed
.
.bfc-root {
position: absolute;
}
Należy pamiętać, że mogą one mieć niepożądane efekty uboczne, takie jak wycinanie przepełnionej zawartości, obliczanie automatycznych szerokości za pomocą algorytmu zmniejszania lub dopasowywanie lub wypływanie. Problem polega na tym, że nie można mieć elementu na poziomie bloku z widocznym przepełnieniem, który ustanawia BFC.
Wyświetlacz L3 rozwiązuje te problemy:
Stworzył flow
i wewnętrzne rodzaje wyświetlaczy lepiej wyrazić układ przepływu typów wyświetlaczy oraz stworzenie wyraźnej przełącznik do dokonywania elementu A BFC korzeniowy. (To powinno wyeliminować potrzebę takich hacków i […])flow-root
::after { clear: both; }
overflow: hidden
Niestety, nie ma jeszcze obsługi przeglądarki. W końcu możemy być w stanie korzystać
.bfc-root {
display: flow-root;
}