一、 FC与BOX的理解
- FC: Formatting Context的缩写,表示页面中的一个渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。常见的有BFC和IFC。
- BOX:CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。
- 盒子的类型:
block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box,并且参与 block fomatting context;
inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
run-in box: css3 中才有; - 非块级盒子的块级容器:
inline-blocks、table-cells和 table-captions
二、BFC的理解
-
BFC: 块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
注意:
1)BFC就是对块级盒子的格式化。block级别的盒子是BFC,inline级别的盒子是IFC。
2) BFC相当于就是变成了一个独立的空间。
3)具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
4)把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。 -
BFC的生成条件:
body根元素
float的值不为none
overflow的值不为visible,比如hidden、auto、scroll等等
display的值为inline-block、table-cell、table-caption
position的值为absolute或fixed -
浏览器对于BFC这块区域的约束规则:
1)生成BFC元素的子元素会一个接一个的放置,垂直方向上他们的起点是一个包含块的顶部,两个相邻子元素之间的垂直距离取决于元素的margin特性,在BFC中相邻的块级元素外边距会折叠。
2)生成BFC元素的子元素中,每一个子元素做外边距与包含块的左边界相接触,(对于从右到左的格式化,右外边距接触右边界),即使浮动元素也是如此(尽管子元素的内容区域会由于浮动而压缩),除非这个子元素也创建了一个新的BFC(如它自身也是一个浮动元素)。
三、BFC的深入理解
-
BFC的布局规则:
1)内部的Box会在垂直方向上一个接一个的放置
2)垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。)
3)每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
4)BFC的区域不会与float的元素区域重叠
5)计算BFC的高度时,浮动子元素也参与计算
6)BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然 -
BFC的应用:
1)防止margin重叠:
在标准文档流当中,两个盒子垂直排列就会产生bfc,一旦产生bfc就会导致盒子的margin重叠。 通过让两个盒子处于独立的bfc当中,就可以避免产生margin重叠现象。
BFC产生外边距折叠的条件:两个相邻元素要处于同一个BFC中。所以,若两个相邻元素在不同的BFC中,就能避免外边距折叠。
如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
举例: 两个盒子垂直排列产生BFC,当设置其中的第一个盒子的父级元素盒子overflow:hidden; 那么这两个盒子就是出于BFC当中,不会发生重叠。
触发前:
触发后:
2)浮动相关的问题:
浮动元素是会脱离文档流的(绝对定位元素会脱离文档流)。如果一个没有高度或者height是auto的容器的子元素是浮动元素,则该容器的高度是不会被撑开的。我们通常会利用伪元素(:after或者:before)来解决这个问题。BFC能包含浮动,也能解决容器高度不会被撑开的问题。
当一个子元素浮动之后,父元素如果没有设置高度,那么父元素会随着子元素的浮动而失去高度,这个时候我们可以给父元素触发BFC,这样父元素就会重新的包裹子元素。因为在bfc中,浮动的元素也参与高度计算。
注意:当父元素设置了overflow以后,相当于开启了BFC,并不是父元素出现了高度包含子元素,而是子元素重新参与了高度运算,撑起了父元素。
触发前:
触发后:
3)自适应两栏布局
根据BFC的布局规则,每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。BFC的区域不会与float box重叠。
举例:通过触发大盒子生成BFC,将大盒子设置overflow:hidden; 来实现自适应两栏布局。当触发大盒子生成BFC后,这个新的BFC不会与浮动的盒子重叠。因此会根据包含块的宽度,和浮动的盒子的宽度,自动变窄。
触发前:
触发后:
4)使用BFC避免文字环绕
对于浮动元素,可能会造成文字环绕的情况(Figure1),但这并不是我们想要的布局(Figure2才是想要的)。要解决这个问题,我们可以用外边距,但也可以用BFC。
在BFC上下文中,每个盒子的左外侧紧贴包含块的左侧(从右到左的格式里,则为盒子右外侧紧贴包含块右侧),甚至有浮动也是如此(尽管盒子里的行盒子 Line Box 可能由于浮动而变窄),除非盒子创建了一个新的BFC(在这种情况下盒子本身可能由于浮动而变窄)。如果创建一个新的BFC那它就不会再紧贴包含块的左侧了。通过overflow:hidden; 进行触发创建一个BFC。
触发前与 触发后:
5) 多列布局中使用BFC
创建一个占满整个容器宽度的多列布局,在某些浏览器中最后一列有时候会掉到下一行。这可能是因为浏览器四舍五入了列宽从而所有列的总宽度会超出容器。但如果我们在多列布局中的最后一列里创建一个新的BFC,它将总是占据其他列先占位完毕后剩下的空间。通过设置最后一个元素的盒子overflow:hidden; 触发生成BFC。