BFC的定义
BFC
全称“Block Formatting Context
”, 中文为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box
参与, 它规定了内部的Block-level Box
如何布局,并且与这个区域外部毫不相干。
在解释什么是BFC
之前,我们需要先知道Box
和Formatting Context
的概念。
Box:css布局的基本单位
Box
是CSS
布局的对象和基本单位,一个页面是由很多个Box
组成的。元素的类型和display
属性,决定了这个Box
的类型。不同类型的Box
,会参与不同的Formatting Context
,会以不同的方式渲染。主要的Box
(盒子)类型有:
block-level box
:display
属性为block
,inline-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
中才有, 这儿先不讲了。
Formatting Context:决定如何渲染文档的容器
Formatting context
是W3C CSS2.1
规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的Formatting context
有Block fomatting context
(简称BFC
)和Inline formatting context
(简称IFC
)。
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素,外部元素也不会影响到BFC内部的元素布局。
BFC的布局规则
- 内部的
Box
会在垂直方向,一个接一个地放置。 Box
垂直方向的距离由margin
决定。属于同一个BFC
的两个相邻Box
的margin
会发生重叠。- 每个盒子(块盒与行盒)的
margin box
的左边,与包含块border box
的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。 BFC
的区域不会与float box
重叠。BFC
就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。- 计算
BFC
的高度时,浮动元素也参与计算。
如何创建BFC
- 根元素,即
html
float
的值不是none
。(left
、right
)overflow
的值不是visible
。(auto
、scroll
、hidden
)position
的值不是static
或者relative
。(absolute
、fixed
)display
的值是inline-block
、inline-flex
、flex
、table-cell
、table-caption
BFC的作用
避免margin重叠(穿透)###
根元素下的两个元素都不是BFC
的效果:
<p>1--看看我的margin是多少</p>
<p>2--看看我的margin是多少</p>
*{
margin: 0;
padding: 0; // 清除所有标签的margin和padding避免干扰
}
p {
color: #f55;
background: yellow;
width: 200px;
line-height: 100px;
text-align:center;
margin: 30px;
}
可以看到同属于HTML
下的两个P
标签的margin
重叠,原因就是BFC的布局规则第二条所讲的属于同一个BFC
的两个相邻Box
的margin
会发生重叠。
那把其中一个P
标签变成BFC
就能解决margin
重叠的问题:
给第一个P
标签包裹一个div
。为什么需要包裹?因为P
中的内容不是Block-level box
,没有margin
属性,因此包上一层div
,给div
设置样式overflow: hidden
(非visible
即可),里面的P
是Block-level box
有margin
属性,就能看到两个P
标签的margin
都生效且不重叠。
<div>
<p>1--看看我的margin是多少</p>
</div>
<p>2--看看我的margin是多少</p>
div{
overflow: hidden;
}
自适应两栏布局###
根据BFC的布局规则第三条:每个盒子的margin box
的左边,与包含块border box
的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此:
<div class="left">LEFT float-left</div>
<div class="right">RIGHT</div>
*{
margin: 0;
padding: 0;
}
body {
margin-left: 50px; /* 测试包含块border box的左边 */
border-left: 1px solid red; /* 测试包含块border box的左边 */
}
.left {
width: 150px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
line-height: 150px;
font-size: 20px;
}
.right {
height: 300px;
background: rgb(170, 54, 236);
text-align: center;
line-height: 300px;
font-size: 40px;
margin-left: 20px; /* 测试盒子的margin box的左边 */
}
浮动的.left
和正常的.right
的margin box
左边都与包含块border box
的左边相接触
要实现两栏布局,根据BFC的布局规则第四条:BFC
的区域不会与float box
重叠,给.right
盒子设置overflow:hidden
(非visible
即可)。
清除浮动
当我们不给父节点设置高度,子节点设置浮动的时候,会发生高度塌陷,这个时候我们就要清楚浮动。
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
.par {
border: 5px solid rgb(91, 243, 30);
width: 300px;
}
.child {
border: 5px solid rgb(233, 250, 84);
width:100px;
height: 100px;
float: left;
}
根据BFC的布局规则最后一条:计算BFC
的高度时,浮动元素也参与计算,给父节点激活BFC
:
参考链接