Razão
O problema é que os elementos flutuantes estão fora de fluxo :
Um elemento é chamado fora de fluxo se for flutuado, absolutamente posicionado ou for o elemento raiz.
Portanto, eles não impactam os elementos circundantes como um elemento em fluxo .
Isso é explicado em 9.5 flutuadores :
Como uma bóia não está no fluxo, as caixas de bloco não posicionadas criadas antes e depois da caixa de bóia fluem verticalmente, como se a bóia não existisse. No entanto, as caixas de linha atuais e subseqüentes criadas ao lado do flutuador são reduzidas conforme necessário para abrir espaço para a caixa de margem do flutuador.
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>
Isso também é especificado em 10.6 Cálculo de alturas e margens . Para blocos "normais" ,
Somente crianças no fluxo normal são levadas em consideração (ou seja, caixas flutuantes e caixas absolutamente posicionadas são ignoradas […])
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>
Solução Hacky: autorização
Uma maneira de resolver o problema está forçando algum elemento em fluxo a ser colocado abaixo de todos os flutuadores. Então, a altura do pai aumentará para envolver esse elemento (e, portanto, os flutuadores também).
Isso pode ser alcançado usando a clear
propriedade :
Essa propriedade indica quais lados das caixas de um elemento não podem
estar adjacentes a uma caixa flutuante anterior.
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>
Portanto, uma solução é adicionar um elemento vazio clear: both
como o último irmão dos carros alegóricos
<div style="clear: both"></div>
No entanto, isso não é semântico. Então, gere melhor um pseudoelemento no final do pai:
.clearfix::after {
clear: both;
display: block;
}
Existem várias variantes dessa abordagem, por exemplo, usar a sintaxe de dois pontos obsoleta :after
para oferecer suporte a navegadores antigos ou usar outras telas no nível de bloco, como display: table
.
Solução: raízes BFC
Há uma exceção ao comportamento problemático definido no início: se um elemento de bloco estabelecer um Contexto de Formatação de Bloco (é uma raiz BFC), ele também envolverá seu conteúdo flutuante.
De acordo com 10.6.7 alturas 'Auto' para raízes de contexto de formatação de bloco ,
Se o elemento tiver descendentes flutuantes cuja borda da margem inferior estiver abaixo da borda de conteúdo inferior do elemento, a altura será aumentada para incluir essas arestas.
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>
Além disso, conforme explicado 9.5 flutuadores , as raízes do BFC também são úteis devido ao seguinte:
A caixa de borda de uma tabela, um elemento substituído no nível de bloco ou um elemento no fluxo normal que estabelece um novo contexto de formatação de bloco […] não devem se sobrepor à caixa de margem de quaisquer flutuadores no mesmo contexto de formatação de bloco que o próprio elemento .
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>
Um contexto de formatação de bloco é estabelecido por
Bloquear caixas com overflow
outras que não sejam visible
, por exemplo,hidden
.bfc-root {
overflow: hidden;
/* display: block; */
}
Recipientes de bloco que não são bloqueiam caixas: quando display
estiver definido para inline-block
, table-cell
ou table-caption
.
.bfc-root {
display: inline-block;
}
Elementos flutuantes: quando float
está definido como left
ou right
.
.bfc-root {
float: left;
}
Elementos absolutamente posicionados: quando position
está definido como absolute
ou fixed
.
.bfc-root {
position: absolute;
}
Observe que eles podem ter efeitos colaterais indesejados, como recortar conteúdo excedente, calcular larguras automáticas com o algoritmo de encolher para ajustar ou ficar fora de fluxo. Portanto, o problema é que não é possível ter um elemento no nível do bloco em fluxo com estouro visível que estabelece um BFC.
A tela L3 soluciona esses problemas:
Criou os tipos de exibição internoflow
e para expressar melhor os tipos de exibição do layout de fluxo e criar uma opção explícita para transformar um elemento em uma raiz BFC . (Isso deve eliminar a necessidade de hacks como e […])flow-root
::after { clear: both; }
overflow: hidden
Infelizmente, ainda não há suporte para o navegador. Eventualmente, poderemos usar
.bfc-root {
display: flow-root;
}