FLOAT坍塌原理及解决方案

什么叫float坍塌?
先看一段简单的代码

<div class = "parent-container">
    <div class = "left-container"></div>
    <div class = "right-container"></div>
</div>

.parent-container {
  width: 400px;
  border: 5px solid #FF6B5B;
}

.left-container {
  float: left;
  height: 100px;
  width: 180px;
  background: #F9BE35;
}

.right-container {
  float: right;
  height: 100px;
  width: 180px;
  background: #68CACA;
}


可以看到,父元素并没有框住两个float子元素,且父元素高度为0,这种现象就是**float坍塌**。

为什么会出现float坍塌?
定位方案的三种流

普通流:包括对块级框的块格式,对行级框的行格式,对块级框和行级框的相对定位;
浮动:在浮动模型中,一个框先按照正常排版来摆放,再将它从排版流中取出并尽可能地向左或向右偏移,其它内容可以排在一个浮动的周围;
绝对定位:在绝对定位模型中,一个框会从排版流中完全脱离出来(它对后续的兄弟没有影响),并相对其包含块来指定其位置(包括 absolute, fixed )。
块格式化上下文

BFC 全称为 Block Formatting Context(块格式化上下文),它是CSS2.1规范定义的页面 CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。简单来说,BFC建立了一个隔离的空间,隔断空间内外元素的相互作用,内部元素相互影响并按正常的布局来排列,同时BFC作为一个块级元素在其所在的文档流中被处理。

BFC创建条件:

根元素或其它包含它的元素;
浮动(float不为 none);
绝对定位元素(absolute或fixed);
行内块 inline-blocks
表格单元格 display: table-cell
表格标题 display: table-caption
overflow不为visible的元素
弹性盒 flex boxs (display: flex 或 inline-flex)
一个BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。

浮动的特性

浮动框可以左右浮动, 直到它的外边缘遇到包含框或者另一个浮动框的边缘;
浮动框脱离了文档的常规流,文档的常规流会忽略浮动框的存在;
浮动框不会影响到块级框的布局,但影响内联框的排列 ;
当浮动框高度超过包含框的时候,包含框不会自动伸缩来闭合浮动框。如果包含框内不存在其它普通流元素,则其高度为0(高度坍塌)。
简单地说,就是浮动会脱离普通流(属于一种比较‘特殊’的脱离,其他内容还会围绕在浮动元素周围),并且创建了新的BFC,而父元素不具备产生 BFC 的条件,这时候父元素无法感知到它的存在,所以它的高度为0。

float坍塌的解决方案
BFC会把它包含的浮动元素高度也算在里面,也就是闭合浮动,大部分解决方案都是围绕着这个特性来实现的。


1). 使用伪元素 :: after

.parent-container::after {
  content: "";  /* 空内容的默认高度为0,避免生成的内容破坏原有布局的高度 */
  display: block;  /* 使生成的内容以块级元素显示,占满剩余空间 */
  height: 0;  /* 当内容不为空时,设置0高度,避免生成的内容破坏原有布局的高度 */
  visibility: hidden;  /* 使生成的内容不可见,避免影响被其盖住的内容的交互事件 */
  clear: both;  /* 关键:清除左右浮动 */}
NOTE:我们在很多网页中看到的 clearfix就是这个原理,一般的做法是设置样式clearfix,然后加在所有需要清除浮动的元素上面。

.clearfix{
  clear: both;
  &: before,
  &: after{
    content:  ' ';
    display:  table;
    clear: both;
  }
}
2). overflow: auto | hidden

.parent-container {
  width: 400px;
  border: 5px solid #FF6B5B;
  overflow: hidden; //或者 overflow: auto, 使父元素拥有创建BFC的条件
}
3). display: table

.parent-container {
  width: 400px;
  border: 5px solid #FF6B5B;
  display: table; //使父元素拥有创建BFC的条件
}
4). position: absolute

.parent-container {
  width: 400px;
  border: 5px solid #FF6B5B;
  position: absolute; //使父元素拥有创建BFC的条件,但是要注意此时在parent-container所在的文档流中,parent-container的布局
}
5). float: left

.parent-container {
  width: 400px;
  border: 5px solid #FF6B5B;
  float: left; //使父元素拥有创建BFC的条件,但是要注意此时在parent-container所在的文档流中,parent-container的布局
}
6). 添加空元素来清除浮动

//增加了无意义的元素,不推荐
<div class = "parent-container">
    <div class = "left-container"></div>
    <div class = "right-container"></div>
    <div class = "clear"></div>
</div>
.clear {
    clear: both;
    height: 0; //for IE
    line-height: 0; //for IE
    font-size: 0; //for IE
}
7). 使用br元素

//增加了无意义的元素,不推荐
<div class = "parent-container">
    <div class = "left-container"></div>
    <div class = "right-container"></div>
    <br clear = "all">
</div>