什么是BFC
BFC(Block formatting context),译为块格式化上下文,是一个独立的渲染区域,规定了内部的子元素如何布局,并且与这个区域外部的关系。
如何触发BFC
- 根元素
html float:不包括noneposition:absoulte,fixeddisplay:inline-block,table-cell,table-caption,flex,inline-flexoverflow:hidden,auto,scroll
当一个html元素满足以上任何一个条件时候,它就形成了一个BFC区域
BFC有哪些规则
BFC内部的块级元素会在垂直方向一个接一个放置- 属于同一个BFC的两个相邻的块级元素
margin会发生重叠 BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素BFC的区域不会与浮动元素重叠- 计算
BFC的高度时,浮动元素也参与计算 - 对于从左往右的格式化,每个元素(块级元素与行内元素)的左边缘,与包含块的左边缘相接触,(对于从右往左的格式化则相反)。即使包含块中的元素存在浮动也是如此,除非其中元素再生成一个
BFC。
BFC有什么用
阻止margin重叠
属于同一个BFC的两个相邻的块级元素margin会发生重叠
<div class="top">top</div>
<div class="bottom">bottom</div>
.top {
height: 50px;
background:green;
margin-bottom:10px
}
.bottom {
height: 50px;
background:green;
margin-top:10px
}
当我们不希望相邻的两个元素margin发生重叠时,只要给其中一个元素包裹一个父元素,创建一个新的BFC就行了
<div class="top">top</div>
<div class="container">
<div class="bottom">bottom</div>
</div>
.top {
height: 50px;
background:green;
margin-bottom:10px;
}
.container{
overflow:hidden
}
.bottom {
height: 50px;
background:green;
margin-top:10px
}
阻止margin溢出
<div class="top">top</div>
<div class="container">
<div class="bottom">bottom</div>
</div>
.top {
height: 50px;
background:green;
}
.container{
/*overflow:hidden */
}
.bottom {
height: 50px;
background:green;
margin-top:10px
}
当父元素container没有形成BFC时,子元素的margin溢出,父元素高度等于子元素的高度50px
当父元素
container形成BFC时,子元素的margin没有溢出,父元素高度等于子元素的高度加上margin值,等于60px
清除浮动
浮动的元素会脱离普通文档流,使得父元素没有高度,常用的清除浮动的一种方法就是让父元素触发BFC
<div class="bfc">
<div class="float"></div>
</div>
.bfc {
overflow:hidden;
}
.float {
float: left;
width: 100px;
height: 100px;
background: green;
}
父元素如果没设置overflow属性,高度只有2px,也就是只有边框的高度
父元素设置overflow属性,形成一个BFC区域,计算高度时,浮动元素也参与计算
自适应两栏布局
<div class="left">left</div>
<div class="right">right</div>
.left {
height: 50px;
width:50px;
float:left;
background:green;
}
.right {
overflow:hidden;
height: 100px;
width:100px;
background:red;
}
当right没有形成BFC时,会被浮动元素left重叠一部分
当
right形成BFC时,BFC的区域不会与浮动元素left重叠
问题
为什么给body设置了overflow:hidden,但是没有形成BFC?
html,body{
margin:0;
}
body{
overflow:hidden;
}
.content{
width:100px;
height:100px;
float:left;
background:green
}
在查阅资料的时候发现,有的博客里有写body会默认创建BFC,显然是不对的,即使当我尝试给body加上overflow:hidden,依然没有形成BFC。
经过测试发现,只有同时给html,body都加上overflow:hidden,又或者给body加上display:inline-block、display:table、position:absolute才能触发BFC
W3C CSS2.1中 BFC是这样被定义的
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
overflow:visible以外的块级元素将创建BFC,除非该值已经扩散到了视口
overflow相关的标准
UAs must apply the 'overflow' property set on the root element to the viewport.
- When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'.
- The 'visible' value when used for the viewport must be interpreted as 'auto'.
- The element from which the value is propagated must have a used value for 'overflow' of 'visible'.
翻译过来大概是这几点意思:
- UA(浏览器)需要将root元素上的
overflow属性置于视口之上; overflow扩散行为:当root元素是html元素且overflow为visible,而且html元素有body作为其子元素,UA则需要将第一个body之上的overflow属性应用于视口;- 用于视口的
overflow: visible将被解析为overflow: auto overflow扩散行为将导致body的使用值为overflow: visible
更直白的阐述: 浏览器的视口一定要有不为visible的overflow属性,但是他本身是没有这个属性的,所以他首先会html要,如果html也没有设置visible属性,他就找body要,无论是html还是body的overflow属性被视口应用之后,其本身的overflow实际效果就变成了visible了,当然,如果html和body都没有设置overflow属性,视口自己默默设定为scroll。
到此,就可以解释为什么给body设置了overflow:hidden,但是没有形成BFC了,因为body的overflow属性被视口抢走了
总结
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。