本文所有的外文翻译都是小久哥自己翻译的,如果你觉得不准确或者想看原文,请点击相关链接。
我们经常使用的清除浮动的代码是:
.clearfix:after {
content:"";
display:block;
height:0;
overflow:hidden;
clear:both;
visibility:hidden;
}
可是为什么要这么写呢?
很久以前的清除浮动
<div class="p">
<div class="c"></div>
<div class="c"></div>
<div class="c"></div>
<div style="clear:both;"></div>
</div>
这样是有缺陷的,我们需要用一个空的div来清除浮动。方法虽然好使,但是得无端使用一个空标签,不推荐使用。
伪元素
既然我们会有一个不需要真正存在的元素,那么为什么不使用伪元素。
然后,就有了使用:after
伪元素来实现清除浮动。
伪类和伪元素是有差别。
伪类有:
伪元素是:
新版清除浮动
当我在看bootstrap的清除浮动时,第三版已经和第二版不一样了。(sass代码)
/* 不用兼容ie6/7的代码里···少了zoom:1,如果要使用,可以添加上 */
@mixin clearfix() {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}
我们来看,bootstrap写了什么。多了:before
,还有display
是table
。
bootstrap在这个文件中的注释有解释
Clearfix
For modern browsers
- The space content is one way to avoid an Opera bug when the
contenteditable
attribute is included anywhere else in the document. Otherwise it causes space to appear at the top and bottom of elements that are clearfixed.- The use of
table
rather thanblock
is only necessary if using:before
to contain the top-margins of child elements.Source: http://nicolasgallagher.com/micro-clearfix-hack/
我大致翻译下:
clearfix
对于现代浏览器 1、文档中任何结点如果包含了
contenteditable
属性时,使用空格占位符是避免Opera浏览器中bug的一个方法。否则,会导致在这个结点上部和下部都会出现空格。 2、如果使用:before
包含子元素的上边距的话,使用table
远比使用block
更为必要。
为什么加 :before
?为什么 table
会比 block
要更好呢?
其实 :before
伪元素没有什么清楚浮动的作用,只是为了实现注释里说的“包含子元素上边距”。
在这里需要补充其他的知识点了“Block Formatting Context”
“Block Formatting Context” 块级格式化上下文
BFC的定义 (W3C官方定义) 是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。 在创建了 Block Formatting Context 的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 ‘margin’ 特性。在 Block Formatting Context 中相邻的块级元素的垂直边距会折叠(collapse)。
在 Block Formatting Context 中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边), 即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的 Block Formatting Context 。
什么样的元素会为其内容生成一个BFC呢?
- 浮动元素,即float:left ¦ right
- 绝对定位元素,即position:absolute ¦ fixed
- 块容器【block containers】(比如inline-blocks,table-cells和table-captions),这些块容器有个特征就是它们不是块级盒子【block boxes】。即display:table-cell ¦ table-caption ¦ inline-block
- 设置了除visible外的overflow值的块盒子【block boxes】,即overflow:hidden ¦ scroll ¦ auto
BFC特性:
- 创建了BFC的元素中,子浮动元素也会参与高度计算 (补充[1])。
- 与浮动元素相邻的、创建了BFC的元素,都不能与浮动元素相互覆盖
- 创建了BFC的元素不会与它们的子元素margin重叠
好了,现在所有的问题都可以解释了,:before
是为了在之前生成一个 display
为 table
的虚拟元素,这个虚拟 table
会生成一个匿名 display:table-cell
(补充[2]) ,从而块级化上下文,这样就实现了包含子元素上边距的问题,同时也清除了浮动。
补充:
- 1.个人理解那句话的意思,也就是清除了浮动,或者说叫,包含浮动。父级如果是一个BFC的话也就可以包含浮动了,这就是为什么父级设置
overflow:hidden
或者display:inline-block
等等可以包含浮动了。但是和清除浮动的差别,视觉上最直观的就是宽度问题,清除浮动之后的宽度是100%,BFC包含浮动的宽度,不一定是100%了。 - 2.关于为什么会生成一个匿名
table-cell
。我也不知道,官方就是这么定义的,在W3C官网中 Anonymous table objects 一段中,关于table对象是这么说:按照css2.1的table模型,文本语言或者HTML中可能没有包含所有的属性,在这些情况下,为了让table
模型正常工作这些“遗漏”的元素必须被定义。任何一个table
元素将会在它里面自动定义一些有用的匿名table
,至少由三层组成,相当于table ¦ inline-table
table-row
table-cell
三层。
参考文献: