我所知道的BFC
刚学习了BFC,听起来好神秘的样子。当然自己在学习的过程中也是困惑重重,这已经是第二次学习了,所以把自己理解的东西总结一下方便自己日后巩固,基本上我学习过程中的很多领悟都是来自于梦想天空的一篇文章:BFC神奇背后的原理。
一,BFC的概念是什么?
Block fomatting context
= block-level box
+ Formatting Context
Box: CSS布局的基本单位
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
;
Formatting context
Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
BFC 定义
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
二,BFC的生成
上文提到BFC是一块渲染区域,那这块渲染区域到底在哪,它又是有多大,这些由生成BFC的元素决定,CSS2.1中规定满足下列CSS声明之一的元素便会生成BFC。
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
看到这里,很多人可能也会像我当初一样感到很困惑,上文明明说只有Block-level box参与,Block-level box又是display属性为block, list-item, table的元素生成的,而这里又说display为inline-block会生成BFC,哈哈,不要急。让我们再好好理清一下思路:
这里只是说Block-level box作为内部元素参与了 inline formatting context。参与 block fomatting context和使触发生成BFC有很大区别,在这里就好像是内部元素Block-level box本身有一个无形的外层,平时是不起作用的一旦被触发生成(如设置了display:inline-block)了BFC外层(注意,只有Block-level box的无形外层有这个能力被触发生成BFC,如果是inline-level box,它的无形外层会被触发生成IFC),这个无形的外层就升级了成了BFC,于是内部元素Block-level box的布局就会按照BFC所规定的6条规则来布局(#¥#%…………blabla,先说到这里吧,以后更深的理解后再补充,下面这个图是借鉴别人的可以加强理解),如图:
三,BFC的约束规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
四,BFC的作用及原理
1.防止垂直 margin 重叠
代码:
1 <style> 2 p { 3 color: #f55; 4 background: #fcc; 5 width: 200px; 6 line-height: 100px; 7 text-align:center; 8 margin: 100px; 9 } 10 </style> 11 <body> 12 <p>Haha</p> 13 <p>Hehe</p> 14 </body>
页面:
两个p之间的距离为100px,发送了margin重叠(塌陷),以最大的为准,如果第一个P的margin为80的话,两个P之间的距离还是100,以最大的为准。
根据BFC布局规则第二条:
Box垂直方向的距离由margin决定。属于同一个BFC(上例中是body根元素的BFC)的两个相邻Box的margin会发生重叠
我们可以在p外面包裹一层容器,并触发该容器生成一个新BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了。
代码:
1 <style> 2 .wrap { 3 overflow: hidden; 4 } 5 p { 6 color: #f55; 7 background: #fcc; 8 width: 200px; 9 line-height: 100px; 10 text-align:center; 11 margin: 100px; 12 } 13 </style> 14 <body> 15 <p>Haha</p> 16 <div class="wrap"> 17 <p>Hehe</p> 18 </div> 19 </body>
效果如下:
2.自适应两栏布局
代码:
1 <style> 2 body { 3 width: 300px; 4 position: relative; 5 } 6 7 .aside { 8 width: 100px; 9 height: 150px; 10 float: left; 11 background: #f66; 12 } 13 14 .main { 15 height: 200px; 16 background: #fcc; 17 } 18 </style> 19 <body> 20 <div class="aside"></div> 21 <div class="main"></div> 22 </body>
页面:
根据BFC布局规则第3条:
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
因此,虽然存在浮动的元素aslide,但main的左边依然会与包含块的左边相接触。
根据BFC
布局规则第四条:
BFC的区域不会与float box重叠。
我们可以通过通过触发main生成BFC
, 来实现自适应两栏布局。
1 .main { 2 overflow: hidden; 3 }
当触发main生成BFC
后,这个新的BFC
不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:
3.清除内部浮动
代码:
1 <style> 2 .par { 3 border: 5px solid #fcc; 4 width: 300px; 5 } 6 7 .child { 8 border: 5px solid #f66; 9 width:100px; 10 height: 100px; 11 float: left; 12 } 13 </style> 14 <body> 15 <div class="par"> 16 <div class="child"></div> 17 <div class="child"></div> 18 </div> 19 </body>
页面:
根据BFC
布局规则第六条:
计算BFC的高度时,浮动元素也参与计算
为达到清除内部浮动,我们可以触发par生成BFC
,那么par在计算高度时,par内部的浮动元素child也会参与计算。
代码:
1 .par { 2 overflow: hidden; 3 }
效果如下:
五,总结
以上的几个例子都体现了BFC
布局规则第五条:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因为BFC
内部的元素和外部的元素绝对不会互相影响,因此, 当BFC
外部存在浮动时,它不应该影响BFC
内部Box的布局,BFC
会通过变窄,而不与浮动有重叠。同样的,当BFC
内部有浮动时,为了不影响外部元素的布局,BFC
计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。