Motivo
Il problema è che gli elementi mobili sono fuori flusso :
Un elemento viene chiamato fuori flusso se viene fluttuato, posizionato in modo assoluto o è l'elemento radice.
Pertanto, non influiscono sugli elementi circostanti come farebbe un elemento in-flow .
Questo è spiegato in 9.5 Float :
Poiché un galleggiante non è nel flusso, le scatole di blocchi non posizionate create prima e dopo la scatola del galleggiante scorrono verticalmente come se il galleggiante non esistesse. Tuttavia, le caselle di riga correnti e successive create accanto al float vengono accorciate se necessario per fare spazio alla casella del margine del 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>
Questo è anche specificato in 10.6 Calcolo delle altezze e dei margini . Per blocchi "normali" ,
Vengono presi in considerazione solo i bambini nel flusso normale (ovvero, le caselle mobili e le caselle posizionate in modo assoluto vengono ignorate […])
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>
Soluzione Hacky: liquidazione
Un modo per risolvere il problema è forzare un elemento in-flow da posizionare sotto tutti i galleggianti. Quindi, l'altezza del genitore crescerà per avvolgere quell'elemento (e quindi anche i galleggianti).
Ciò può essere ottenuto utilizzando la clear
proprietà :
Questa proprietà indica quali lati dei riquadri di un elemento potrebbero non
essere adiacenti a un riquadro mobile precedente.
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>
Quindi una soluzione sta aggiungendo un elemento vuoto con clear: both
l'ultimo fratello dei float
<div style="clear: both"></div>
Tuttavia, ciò non è semantico. Quindi meglio generare uno pseudo-elemento alla fine del genitore:
.clearfix::after {
clear: both;
display: block;
}
Esistono più varianti di questo approccio, ad esempio l'utilizzo della sintassi dei due punti deprecata :after
per supportare i vecchi browser o l'utilizzo di altri display a livello di blocco come display: table
.
Soluzione: radici di BFC
Esiste un'eccezione al comportamento problematico definito all'inizio: se un elemento a blocchi stabilisce un contesto di formattazione dei blocchi (è una radice BFC), avvolgerà anche il suo contenuto mobile.
Secondo le altezze 10.6.7 "Auto" per le root di contesto di formattazione dei blocchi ,
Se l'elemento ha discendenti mobili il cui bordo del margine inferiore è inferiore al bordo del contenuto inferiore dell'elemento, l'altezza viene aumentata per includere tali bordi.
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>
Inoltre, come spiegato 9.5 Float , anche le radici BFC sono utili a causa di quanto segue:
Il riquadro di bordo di una tabella, un elemento sostituito a livello di blocco o un elemento nel flusso normale che stabilisce un nuovo contesto di formattazione del blocco […] non deve sovrapporsi al riquadro del margine di alcun float nello stesso contesto di formattazione del blocco dell'elemento stesso .
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>
Un contesto di formattazione dei blocchi è stabilito da
Bloccare le scatole con overflow
altro visible
, ad eshidden
.bfc-root {
overflow: hidden;
/* display: block; */
}
Blocca contenitori che non sono caselle di blocco: quando display
è impostato su inline-block
, table-cell
o table-caption
.
.bfc-root {
display: inline-block;
}
Elementi mobili: quando float
è impostato su left
o right
.
.bfc-root {
float: left;
}
Elementi posizionati in modo assoluto: quando position
è impostato su absolute
o fixed
.
.bfc-root {
position: absolute;
}
Si noti che potrebbero avere effetti collaterali indesiderati, come il ritaglio del contenuto traboccante, il calcolo delle larghezze automatiche con l' algoritmo di riduzione o l'adattamento o il fuori flusso. Quindi il problema è che non è possibile avere un elemento a livello di blocco in-flow con overflow visibile che stabilisce un BFC.
Display L3 risolve questi problemi:
Creato i tipi di visualizzazione internaflow
e per esprimere meglio i tipi di visualizzazione del layout di flusso e per creare un interruttore esplicito per rendere un elemento una radice BFC . (Questo dovrebbe eliminare la necessità di hack come e […])flow-root
::after { clear: both; }
overflow: hidden
Purtroppo, non esiste ancora alcun supporto per il browser. Alla fine potremmo essere in grado di usare
.bfc-root {
display: flow-root;
}