Os elementos flutuantes dentro de uma div flutuam para fora da div. Por quê?

274

Digamos que você tenha um div, dê um definido widthe coloque elementos nele, no meu caso um imge outro div.

A ideia é que o conteúdo do contêiner divfaça com que ele divse estique e seja um pano de fundo para o conteúdo. Mas quando faço isso, o conteúdo divdiminui para se ajustar aos objetos não flutuantes, e os objetos flutuantes ficam totalmente para fora, ou meio para fora, meio para dentro e não têm qualquer influência sobre o tamanho do grande div.

Por que é isso? Há algo que está faltando e como posso obter itens flutuantes para esticar o heightconteúdo de um contêiner div?

DavidR
fonte

Respostas:

398

O mais fácil é colocar overflow:hiddena div pai e não especificar uma altura:

#parent { overflow: hidden }

Outra maneira é também flutuar a div pai:

#parent { float: left; width: 100% }

Outra maneira usa um elemento claro:

<div class="parent">
   <img class="floated_child" src="..." />
   <span class="clear"></span>
</div>

CSS

span.clear { clear: left; display: block; }
Doug Neiner
fonte
17
Funciona, mas agora estou duas vezes mais confuso: existe uma explicação para isso ou é exatamente assim?
DavidR
8
Sim, existe uma explicação, mas desde então a esqueci :( É exatamente como é. O sistema overflow:hiddenforça o navegador da melhor maneira possível para conter os elementos filhos do pai. É por isso que o corrige.
Doug Neiner
5
Eu acho que a explicação overflow: hiddenestá aqui: link . E muito obrigado, ele trabalhou para mim
Vikas Arora
6
@DavidR A explicação mais fácil é que o html / css é uma peça de tecnologia datada, mal pensada e mal implementada. Na verdade, esse raciocínio realmente explica muitas peculiaridades html / css que você sem dúvida encontrou desde que publicou este post.
Leve
1
Lembre-se de que overflow: hiddenapenas ocultará qualquer parte de um elemento que flua para fora do contêiner pai. Para mim, isso fez com que certos pedaços de texto se tornassem ilegíveis.
Top Cat
160

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.

insira a descrição da imagem aqui

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 […])

insira a descrição da imagem aqui

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 clearpropriedade :

Essa propriedade indica quais lados das caixas de um elemento não podem estar adjacentes a uma caixa flutuante anterior.

insira a descrição da imagem aqui

Portanto, uma solução é adicionar um elemento vazio clear: bothcomo 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 :afterpara 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.

insira a descrição da imagem aqui

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 .

insira a descrição da imagem aqui

Um contexto de formatação de bloco é estabelecido por

  • Bloquear caixas com overflowoutras 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 displayestiver definido para inline-block, table-cellou table-caption.

    .bfc-root {
      display: inline-block;
    }
  • Elementos flutuantes: quando floatestá definido como leftou right.

    .bfc-root {
      float: left;
    }
  • Elementos absolutamente posicionados: quando positionestá definido como absoluteou 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;
}
Oriol
fonte
1
Portanto, as caixas flutuantes não são reconhecidas por seus contêineres pai, portanto, a altura diminui, mas são reconhecidas por seus irmãos, daí o clearfix?
symlink
@symlink Sim, os contêineres pai não crescem para incluir carros alegóricos, a menos que sejam raízes BFC. Irmãos que não são raízes de BFC não são afetados diretamente por blocos (mas suas caixas de linha são). No entanto, a folga os move abaixo de qualquer flutuador anterior.
Oriol
"Irmãos que não são raízes do BFC não são diretamente afetados pelos blocos (mas suas caixas de linha são)." - Você pode esclarecer isso, por favor? Você quer dizer que, neste jsFiddle: jsfiddle.net/aggL3Lk7/2 , a imagem embutida flutuante não está afetando a extensão (portanto, a borda da extensão a sobrepõe), mas a imagem está afetando o texto (que é a caixa de linha), como é mostrado pelo fato de o texto não estar sobreposto à imagem?
symlink
1
@ sylink Sim, exatamente. Bem, no violino, a borda pertence aos pais, mas seria basicamente a mesma para os irmãos: jsfiddle.net/aggL3Lk7/3
Oriol
1
Eu concordo. Essa deve ser a resposta aceita. É interessante para mim que o W3 esteja chamando da maneira que somos forçados a codificar um "hack". Alguém estragou tudo.
DR01D
11

Não falta nada. O Float foi projetado para o caso em que você deseja que uma imagem (por exemplo) fique ao lado de vários parágrafos de texto, para que o texto flua ao redor da imagem. Isso não aconteceria se o texto "esticou" o contêiner. Seu primeiro parágrafo terminaria e, em seguida, seu próximo parágrafo começaria sob a imagem (possivelmente várias centenas de pixels abaixo).

E é por isso que você está obtendo o resultado que é.

Lucas Wilson-Richter
fonte
3
Como isso tem alguma coisa a ver com o elemento flutuante esticar adequadamente a altura dos pais?
Leve
11

Em alguns casos, ou seja, quando (se) você está apenas usando floatpara que os elementos fluam na mesma "linha", você pode usar

display: inline-block;

ao invés de

float: left;

Caso contrário, o uso de um clearelemento no final funcionará, mesmo que ele vá contra a granulação para precisar de um elemento para fazer o que deveria ser um trabalho CSS.

LSerni
fonte
11

Aqui está uma abordagem mais moderna:

.parent {display: flow-root;} 

Não há mais correções.

ps Usando estouro: oculto; esconde a sombra da caixa tão ...

pendingfox
fonte
Também funciona no Safari 11
pendingfox
7

Obrigado LSerni, você resolveu isso para mim.

Para alcançar isto :

+-----------------------------------------+
| +-------+                     +-------+ |
| | Text1 |                     | Text1 | |
| +-------+                     +-------+ |
|+----------------------------------------+

Você tem que fazer isso :

<div style="overflow:auto">
    <div style="display:inline-block;float:left"> Text1 </div>
    <div style="display:inline-block;float:right"> Text2 </div>
</div>
Flyout91
fonte
4

Como Lucas diz, o que você está descrevendo é o comportamento pretendido para a propriedade float. O que confunde muitas pessoas é que o float foi muito além do uso original pretendido para compensar as deficiências no modelo de layout CSS.

Dê uma olhada no Floatutorial se quiser entender melhor como essa propriedade funciona.

Sam Murray-Sutton
fonte
0

Você pode fazer facilmente com o primeiro, você pode flexionar a div e aplicar o conteúdo justificado à direita ou à esquerda e seu problema está resolvido.

<div style="display: flex;padding-bottom: 8px;justify-content: flex-end;">
					<button style="font-weight: bold;outline: none;background-color: #2764ff;border-radius: 3px;margin-left: 12px;border: none;padding: 3px 6px;color: white;text-align: center;font-family: 'Open Sans', sans-serif;text-decoration: none;margin-right: 14px;">Sense</button>
				</div>

Vijay Tiwari
fonte