一、 什么是BFC?
1 CSS布局的基本单位:Box(盒模型)
Box是CSS布局的对象和基本单位,一份网页由多个Box根据其排列规则组合而成。根据CSS规范,每个HTML元素都有一个默认的display
属性值,用于确定元素的类型,进而决定这个Box的类型。
div、h1~6、等默认display属性值为:block;
span、a等默认display属性值为:inline
img、等默认display属性值为:inline-block
Box类型:
-
Block-level box
:display
属性值为block
、list-item
、table
的元素,会生成Block-level box
; -
Inline-level box
:display
属性值为inline
、inline-block
、inline-table
的元素,会生成Inline-level box
;
2 Formatting Context
Formatting Context是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
Formatting Context决定了Box内子元素如何定位,以及Box与其他元素的关系及相互作用
Box类型不同,其Formatting Context(决定如何渲染文档的容器)不同,Box内的元素以不同方式进行渲染,常见的Formatting Context:
- Block Formatting Context(BFC):只有
Block-level box
参与; - Inline Formatting Context(IFC):
Inline-level box
参与;
3 BFC
Block Formatting Context(“块级排版上下文”),是一个 独立的渲染区域,只有Block-level box
参与,规定内部的Block-level box
如何布局,与这个区域外不相干
4 BFC布局规则
- 同一个BFC内部的Box在垂直方向,一个接一个地排列;
- Box垂直方向的间距由
margin
值决定,属于同一个BFC内的两个相邻Box的margin
值会发生重叠,重叠的结果:间距为较宽的margin
值; - BFC内部每个Box的左边
margin
与其包含块的左边border
相接处(对于从左往右的格式化,否则相反),即使浮动也是如此; - 包含块内部子元素的每个BFC不会重叠,如果设置
float
属性,会在水平依次排开 - BFC是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面的元素(反之,亦反);
- 计算BFC的高度时,其内的浮动元素也参与;
二、生成BFC的元素
- 根元素;
-
float
属性值不为none
; -
position
属性值为absolte
或者fixed
; -
display
属性值为inline-block
、table-cell
、table-caption
、flex
、inline-flex
; -
overflow
属性值不为visible
。
三、BFC的作用与原理
1 自适应两栏布局
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
background: #fcc;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
根据第3条规则:BFC内部每个Box的左边
margin
与其包含块的左边border
相接处(对于从左往右的格式化,否则相反),即使浮动也是如此;
注解规则3:.aside
和.main
都在根元素(包含块的BFC)下,其内的每个Box的margin left
都与根元素的border left
相接触。.aside
由于float:left;
向上浮动(显示层级变高),变成了一个BFC,并且脱离包含块中BFC的文档流,.main
会与.aside
重叠
根据第4条规则:包含块内部子元素的每个BFC不会重叠,如果设置
float
属性,会在水平依次排开
注解规则四:因为.main
没有其display
属性默认值为block
,没有生成包裹它的子BFC,所以会与.aside
重叠,如果将.main
生成一个包含的BFC,.main
和.aside
会分开。
将.main
设置生成BFC的方法:
-
.main
设置为overflow:hidden;
:溢出隐藏,.main
生成BFC后,其宽度继承自body
为300px
,平铺开后,加上.aside
宽度应该为400px
,超过了包含块的宽度,溢出隐藏指隐藏右侧超出的100px
;
-
.main
设置为float:left;
如果不指定.main
的宽度,则.main
不会显示。元素设置浮动后,如果不显式指定宽度,其宽度有内容撑开,没有内容时则不显示。
2 清除内部浮动
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.par {
border: 5px solid #fcc;
width: 300px;
}
.child {
border: 5px solid #f66;
width:100px;
height: 100px;
float: left;
}
</style>
</head>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
</html>
根据第6规则:计算BFC的高度时,其内的浮动元素也参与;
注解规则6:由于两个.child
元素设置了float
(生成两个子BFC),脱离文档流,并且其包含块不是没有BFC,所以高度没有被撑开,只显示了包含块的上下边框。
将包含块生成BFC即可撑开高度,利用浮动元素也参与BFC高度的计算。
/*利用overflow:hidden将par生成BFC*/
.par {
overflow: hidden;
}
3 防止margin
垂直重叠
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
</head>
<body>
<p>Haha</p>
<p>Hehe</p>
</body>
</html>
根据第2条规则:Box垂直方向的间距由
margin
值决定,属于同一个BFC内的两个相邻Box的margin值会发生重叠,重叠的结果:间距为较宽的margin
值;
注解规则2:由于两个p
元素没有生成BFC,并且都在根元素内,根据BFC第6条规则,margin
值会发生重叠。只需要在一个p
元素外包裹一层容器,并将该容器生产一个BFC,便不会再重叠。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
.wrap {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
</head>
<body>
<p>Haha</p>
<div class="wrap">
<p>Hehe</p>
</div>
</body>
</html>
三、总结归纳
规格第5条:BFC是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面的元素(反之,亦反);
- BFC外部和内部的元素不会相互影响 ,所以BFC外部存在浮动时,不会影响其内部Box的布局,BFC通过溢出隐藏不与浮动有重叠;
- 当BFC内部有浮动时,为不影响外部元素的布局,计算BFC高度时要考虑浮动元素的高度。(避免
margin
的重叠道理相同:利用一个BFC将其包裹起来)
自己理解的BFC:
BFC是存在于普通文档流中,用于记录Box自身尺寸,不会随浮动、定位、溢出隐藏而改变。相当于只位于普通文档中的Box模型,其布局不会因为BFC内部元素改变而改变。
参考博文: