BFC的特征有以下两点:
内部的Box会在垂直方向,一个接一个地放置。
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
这两点我十分不明白,为什么说内部的box会在垂直方向上一个一个放置,这不是只有内部box都是块级元素的情况下才会出现的吗?如果元素是行内级元素或者浮动元素,不就不会这样了吗?
第二点也是同理,为什么说每个元素的margin box的左边都会与包含块border box的左边相接触?即使浮动也是如此?可是如果浮动或者行内级,第二个元素的margin不会与包含块边缘接触呀?
而且,哪怕接触,也应该适合包含块的content box相接触吧,为什么会是border box呢?
(为了方便浏览把疑惑的问题加粗了,不是为了博存在感,请见谅~)
关于第一点:这个我现在还不太清楚。等看完W3C文档仔细研究一下再回答
关于第二点:你要先理解包含块的概念。包含块不是一个完整的box,一个完整的box包含margin-box,border-box,padding-box,content-box。即使设置为0,也是存在的。
包含块有可能是某个盒子的content-box,也有是某个盒子的padding-box。这取决于被包含块所包含的盒子的position属性。
例如:如果某个盒子 position 属性是 absolute 的话,包含块就是由它的最近的 position 的值不是 static (fixed, absolute, relative, or sticky)的祖先元素的padding-box组成。
简单的说,你使用子绝父相定位的时候,位置是相对于包含块而言的,也就是父元素的padding-box。而不是content-box。
又例如:某个盒子 position 属性是 static 或 relative 的话,包含块就是由它的最近的祖先块元素的content-box的边缘组成的。
简单的说,默认定位的盒子,其包含块就是块级父元素的content-box
再例如,position 为 fixed 盒子的包含块为视口,
简单的说,固定定位盒子你怎么滚动始终在所看到的窗口上。
有了包含块的概念,再回过头去看规范中的关于bfc的英文原文。
In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
原文翻译,在一个bfc中,每一个盒子的左外边距应该和包含块的左边接触。这句话有两个地方值得注意
第一、 bfc中的盒子应该与其自身的包含块相接触,而非与bfc盒子相接触,这个包含块有可能是bfc中的一部分,也有可能和bfc无关。
第二、bfc中的盒子是与其包含块的 left edge 相接触,而不是包含块的left-border相接触。因为包含块并非一个完整的盒子,不可能有left-border。 left edge 正确的翻译为左边缘。
看代码理解:
效果图:
div.bfc使用position:abosulute形成了一个bfc。它有三个子盒子。一个浮动,一个绝对定位,一个固定定位。
浮动盒子的定位属性为默认的static,因此其包含块为最近的块级祖先元素的content-box。正好就是bfc父盒子的内容区,因此按照规范,与bfc的content-box的左边缘接触,没毛病。
绝对定位盒子,其包含块为使用最近的使用了定位的祖先元素的padding-box,同样也是bfc盒子的,但这次指的是padding区域。于是先与bfc盒子的padding-box左边缘接触(也就是bfc盒子border-left的右边),当然,定位属性还有自身的规范,必须按照定位属性top left right bottom等找到自己位置。
固定定位盒子,其包含块为视口,同理与视口左边缘接触,再按照另行的规范,定位找到自己位置。没毛病。这个例子说明了,盒子的包含块,有可能与bfc盒子没半毛钱关系。
第二句翻译:即使存在浮动盒子也应该如此(如此的意思就是布局应该按照上述的规则进行),除非子盒子又形成了一个新的bfc。
这句话正确的理解方式为,一个bfc中,如果存在一个浮动的盒子,而其他盒子并没有形成新的bfc,那么所有的子盒子都应该触碰到其包含块的左边缘。举个例子,一个父盒子使用overflow:hidden形成bfc,其中有个子盒子,一个浮动,另一个不浮动。那么浮动盒子会盖住不浮动盒子,但是两个盒子都会触碰到bfc的content-box。这个你很容易理解对吧。
如果有两个浮动的盒子,也就是你的问题所在,第二个盒子会追在第一个盒子屁股后面,是不是违反规范了?你太年轻了,第二句话不说的很明白了吗。除非盒子自身又形成了一个新的bfc,第二个盒子使用浮动,不就形成了一个新的bfc了吗。