一、BFC(Block Formatting Context)块级格式化上下文
注意:
BFC首先是块,其次需要具备下面的条件之一才可以(通俗来说,BFC就好比一所985或者211的高校,想要成为985或者211的高校,它是有前提条件的,首先他得是一所大学,不能拿一个小学来说,就好比BFC得先是块,下一步才能是BFC;当满足了前提条件,再需要具备其他的条件才可以。)
在正式说BFC具体内容之前,先说一下Box和Formatting Context是个什么东西:
-
Box
大家应该都不陌生,
Box是CSS布局的对象和基本单位,直观点说就是一个页面是由很多个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 fomatting context。run-in box:CSS3中新增的,是一个块/行内元素混合,可以使某些块级元素成为下一个元素的行内部分,目前很少有浏览器支持该元素。
-
Formatting context
Formatting context是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。常见的
Formatting context:Block Formatting Context(简称BFC)Inline Formatting Context(简称IFC)- CSS2.1 中只有
BFC和IFC, CSS3中还增加了GFC和FFC。
BFC(Block formatting context)直译为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与创建BFC, 它规定了内部的Block-level Box如何布局,并且与这个独立盒子里的布局不受外部影响,当然也不会影响到外面的元素。
二、BFC的触发条件:
- 根元素 (当前文档中 html 标签就是一个
BFC); float的值不为none的其他属性值;overflow的值不为visible的其他属性值(有hidden,auto,scroll);display的值为inline-block/table-cell/table-caption/flex/inline-flex;position的值为absolute或fixed;
三、BFC的特性(优点)以及应用场景
1、box垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻box的margin会发生重叠
应用场景:可以解释为什么margin上下会重叠,以及解决方法的原因
-
问题分析:默认情况下,两个相邻的
box的margin会发生重叠的原因,是因为box1和box2都属于html,而html是BFC。因为BFC里面规定了,属于同一个BFC的两个相邻box的margin会发生重叠,所以box1和box2重叠了,也就是外边距重叠。默认情况下,两个相邻的box的margin会发生重叠:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body{margin: 0;padding: 0;} .box1{width: 300px;height: 300px;background: red;margin-bottom: 50px;} .box2{width: 400px;height: 400px;background: yellow;margin-top: 100px;} </style> </head> <body> <div class="box1"></div> <div class="box2"></div> </body> </html>如图所示:
-
解决方案:
- 重叠之后,想要不重叠,可以给后面的元素添加一个父元素并且添加声明
overflow: hidden;来解决(添加其他声明也可以,只要可以触发BFC即可) - 可以解决的原因是因为,当给box2添加了父元素并且添加了
overflow:hidden;之后,这个父元素boxs就是BFC了,当前的结构里面box1属于BFC html,box2属于BFC boxs,这个时候box1和box2就不属于同一个BFC了,那么也就不会发生重叠了。
具体代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body{margin: 0;padding: 0;} .box1{width: 300px;height: 300px;background: red;margin-bottom: 50px;} .box2{width: 400px;height: 400px;background: yellow;margin-top: 100px;} .boxs{overflow: hidden;} </style> </head> <body> <div class="box1"></div> <div class="boxs"> <div class="box2"></div> </div> </body> </html>如图所示:实现效果(给box2添加父元素并声明触发BFC即可解决)
- 重叠之后,想要不重叠,可以给后面的元素添加一个父元素并且添加声明
2、计算BFC的高度时,浮动元素也参与计算
应用场景:可以解释为什么高度塌陷可以用 overflow:hidden等方法解决
-
问题分析:为什么添加了
overflow:hidden;就可以解决高度塌陷,是因为添加了之后,就触发ul为BFC,而BFC里面规定了,计算BFC高度的时候,浮动元素也参与计算。ul未触发BFC时,li浮动时,ul高度塌陷:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body,ul{margin: 0;padding: 0;} ul{border: 3px solid red;} ul li{float: left;list-style: none;border: 1px solid yellow;} </style> </head> <body> <ul> <li>浮动元素</li> <li>浮动元素</li> <li>浮动元素</li> <li>浮动元素</li> </ul> </body> </html>如图所示:
当给
ul添加了overflow:hidden;之后,就触发了ul为BFC,而计算BFC高度的时候,浮动元素也参与计算:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body{margin: 0;padding: 0;} ul{border: 3px solid red;overflow: hidden;} ul li{float: left;list-style: none;border: 1px solid yellow;} </style> </head> <body> <ul> <li>浮动元素</li> <li>浮动元素</li> <li>浮动元素</li> <li>浮动元素</li> </ul> </body> </html>如图所示:
overflow:auto/scroll或者display:flex/inline-flex/table等,都可以解决高度塌陷,也是因为触发了ul为BFC
3、BFC的区域不会与float box发生重叠
应用场景:自适应两栏布局或者三栏布局
-
问题分析:
- 上面的一个元素浮动,下面的一个元素没有浮动,那么会发生重叠,原因是因为浮动之后不占据位置,所以后面的元素会上去;
- 当给下面的元素添加了
float、overflow、display的时候就不重叠了,原因是因为给了这些声明之后,就触发了下面的元素为BFC,而BFC里面规定了,BFC区域不会与浮动盒子发生重叠。 - 如果既要
BFC区域不会与float box发生重叠,又要右边的容器自适应:float不可以;overflow:hidden、auto、scroll;可以;display:flex、inline-flex;可以。
当上面元素设置浮动,下面元素没有浮动,那么就会发生重叠:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> .left {width: 300px;height: 300px;background: red;float: left;} .right {height: 400px;background: yellow;} </style> </head> <body> <div class="left">left</div> <div class="right">right</div> </body> </html>如图所示:
当下面元素添加声明,触发
BFC,就不会与浮动盒子发生重叠:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> .left {width: 300px;height: 300px;background: red;float: left;} .right {height: 400px;background: yellow;overflow: hidden;} </style> </head> <body> <div class="left">left</div> <div class="right">right</div> </body> </html>如图所示:
-
应用案例:
- 自适应两栏布局
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body,ul,ol{ margin: 0; padding: 0;} html,body{height: 100%;} .left{width: 300px;height:500px;background: #0000FF;float: left;} .right{height: 600px;background: yellow;overflow: hidden;} </style> </head> <body> <div class="left">left固定</div> <div class="right">right自适应</div> </body> </html>实现效果如图所示:
可以实现右侧自适应的方法属性有: overflow: hidden、auto、scroll; display: flex、inline-flex;
- 三栏布局
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body{ margin: 0; padding: 0;} html,body{height: 100%;} .left{ width: 100px;height: 200px;background: red;float: left; } .center{ height: 400px;background: #00FFFF;overflow: hidden;margin-right: 200px; } .right{ width: 200px;height: 300px;background: #008000;float: left;position: absolute;top: 0;right: 0; } </style> </head> <body> <div class="left">left</div> <div class="center">center</div> <div class="right">right</div> </body> </html>实现效果如图所示:
不同分辨率下左右两侧内容固定不变,中间内容自适应(下面因为图片放大了所以左右两侧显得变大了,实际上并没有改变大小):
在BFC中,最重要的就是上面三组特性,每个特性的应用场景都是非常广泛的,在现实开发过程中,也会经常用到。至于下面的三个特性就简单了解一下就可以了。
4、BFC内部的Box会在垂直方向,一个接一个的放置。
5、每个元素的margin box的左边会与包含块border box的左边相接触(对于从左到右的格式化,否则相反),即使存在浮动也会如此。
6、BFC就是页面上的一个独立容器,容器里面的元素不会影响到外面的元素。
到这里 BFC 就结束了,总结一下 BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。