【深圳】DJI 大疆创新 互联网团队 前端及大量职位招聘中 (内推 15-50k + 丰厚年终 + 股份)简历请发至 evan.zhou@dji.com, 合适的话当天回复,当天内推。 更多福利

产生问题

先从一个简单的例子说起:

1
2
3
4
<div class="parent">
<div class="child-left"></div>
<div class="child-right"></div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.parent {
width: 200px;
margin: 30px auto;
border: solid 5px #3498db;
}
[class^='child'] {
opacity: 0.8;
}

.child-left {
float: left;
height: 100px;
width: 120px;
background: #2ecc71;
}
.child-right {
float: right;
height: 100px;
width: 80px;
background: #e74c3c;
}

效果大概是这样:(设置透明度只是为了演示)
坍塌
我们看到的效果是父元素并没有包裹住,两个 float 的子元素,并且它自身的高度为 0。

相信很多前端er都曾为此困惑不已,为什么子元素都 float 会导致父元素高度为 0?据说 clear:both 可以用来清除浮动,那为什么给父元素加上之后没有效果?google,百度一番之后找到了解药–clearfix。

什么是clearfix

.clearfix 可以说是很多前端开发者不可缺少的补丁。它可以用来闭合浮动,修复父元素高度坍塌的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
.clearfix:before,
.clearfix:after {
content: "";
display: table;
}

.clearfix:after {
clear: both;
}

.clearfix {
zoom: 1; /* ie 6/7 */
}

用法,还是使用上面的例子

1
2
3
4
<div class="parent clearfix">
<div class="child-left"></div>
<div class="child-right"></div>
</div>

clearfix

给父元素加上 clearfix 类名就搞定了。
喜欢折腾的同学肯定知道其实给父容器增加下列属性中的一个都能达到相同效果

1
2
3
4
overflow: auto;
display: table;
position: absolute;
float: left;

背后究竟发生了什么?带着问题,继续学习几个新名词。

清除浮动 还是 闭合浮动 ?

可能是由于 clear 属性命名的关系,我们经常只会说清除浮动,但是确切地说清除浮动对应的是 clear: left|right|both|none|inherit;
而上面的例子,我们是想让浮动的元素闭合,减少浮动带来的影响,应该是属于闭合浮动的范围。

那些年我们一起清除过的浮动

文档流

从我接触前端开始,听到的都是文档流,文档流,但真正的称谓应该叫做普通流或常规流(英文为:normal flow )。我的理解是按照HTML标签的位置顺序把元素从上到小,从左到右逐行排版的过程。

在 css2.1 中提到的 w3c-定位方案有三种:

>

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

所以浮动也会脱离普通流,但属于一种比较‘特殊’的脱离,其他内容还会围绕在浮动元素周围,这时候父元素无法感知到它的存在。

BFC

BFC 全称为 Block Formatting Context,很多人直译叫它块格式化上下文。它是CSS2.1规范定义的,是页面 CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。

创建

下面的情况会产生新的BFC:

  • 根元素或其它包含它的元素
  • 浮动 (元素的 float 不为 none)
  • 绝对定位元素 (元素的 position 为 absolute 或 fixed)
  • 行内块 inline-blocks (元素的 display: inline-block)
  • 表格单元格 (元素的 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素的 display: table-caption, HTML表格标题默认属性)
  • overflow 的值不为 visible的元素
  • 弹性盒 flex boxes (元素的 display: flex 或 inline-flex)

范围

一个BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。

特性

BFC最显著的效果是建立一个隔离的空间,断绝空间内外元素相互的作用。当然,还有更多的特性:

  • 内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流);
    处于同一个BFC中的元素相互影响,可能会发生margin collapse;
  • 每个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
  • 计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算;
  • 浮动盒区域不叠加到BFC上;

看到这里,再回头想想之前的几个小问题:

问题解决

为什么坍塌?

为什么会坍塌? float 脱离了普通流,并且创建了新的BFC,而父元素不具备产生 BFC 的条件,所以它的高度为0。

如何解决?

通过了解BFC的特性我们知道,BFC会把它包含的浮动元素高度也算在里面,也就是闭合浮动。拿 overflow: auto 举例:
overflow: auto 并不会闭合浮动,而是 overflow: auto 会创建一个新的BFC,避免浮动的元素侵入其他元素。

父元素上clear: both 不起作用?

这应该算是语义理解错了,clear: both 是让两边都不能有浮动元素,清除上方元素“浮动导致高度坍塌”,所以在父元素上用是没有效果的,通常放在浮动元素的下方,同样也会引起父元素拉伸以包裹浮动元素。

推荐阅读

废话

个人认为类似这类问题在 BAT 面试中属于必得分题,如果答不出来,那迎娶白富美就没你什么事了。
之前一直花心思在如何快速吃成胖子上,没有静下心来沉淀,这就是基础不扎实的表现。
补充:我写文章是为了方便自己复习,总结,也是推动自己学习的主要途径,还有练习写文档的能力,最后的最后才是跟别人分享~所以不建议大家看我们的文章,遇到问题,推荐去 google,翻 w3c 文档,或其他有保证的网站。快餐一时爽,可不能贪杯!

如需转载,请注明出处: http://w3ctrain.com / 2016/03/28/float-secret/