目录
一、BFC定义
Formatting context(格式化上下文) 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用
BFC是Block Formatting Contexts(块级格式化上下文)的缩写,也就是按照普通块级方式定位渲染
具有BFC特性的元素是一个独立的布局环境,可看着为一个不受外界影响的隔离容器,里面的盒子会沿着父元素边框排列,无论怎样都不会影响到外边去
二、BFC布局规则
1、闭合浮动:浮动的元素会被父级计算高度(父级触发了BFC)--> 可清除浮动
为了保持BFC内部的元素不影响外界布局的封闭性,因此内部的浮动元素也会被BFC容器计算高度,避免对外界元素造成影响,实现了清除浮动效果
2、非浮动元素触发了BFC,则不会占用浮动元素的位置
3、margin不会传递给父级造成外边距塌陷(父级触发了BFC)
4、两个相邻元素上下外边距合并 --> 给其中一个元素增加一个父级,并让其父级触发BFC即可
5、block定位布局方式,从上到下
三、什么时候触发BFC
1、浮动元素 --> 即除了 float:none 以外
2、绝对定位元素 --> position:absolute、fixed,已经脱离普通流了,但是优先级高于BFC规则
3、display的值为 inline-block、table-cell、flex、table-caption、inline-flex
4、overflow 除了 visible 以外的值(hidden、auto、scroll)
四、了解BFC的作用
1、解决外边距margin合并或塌陷问题
①.相邻元素垂直外边距的合并 --> 将其中一个盒子再套一个父级,并给该父级触发BFC即可
②.嵌套块元素垂直外边距的塌陷 --> 给父级触发BFC即可防止子盒子的margin传递给父级
2、用BFC阻止元素被浮动元素覆盖
①.普通文字环绕效果 --> 文字环绕float盒子,但左边浮动盒子区域还是被浮动盒子覆盖了(半脱标)
②. 自适应两栏布局 --> 普通流盒子触发BFC不会占用浮动的位置
3、用于清除浮动
浮动的盒子脱离标准流但不脱离文本流,即浮动的盒子是没有实际高度的,为了不影响后面标准流的布局,需要清除浮动
①.没有触发BFC的普通父盒子,里面的浮动元素不会被计入高度,高度为 0
<style type="text/css">
.box{
width: 200px;
background-color: pink;
}
.test{
float: left;
width: 100px;
height: 100px;
background-color: #008000;
}
</style>
</head>
<body>
<div class="box">
<div class="test"></div>
</div>
</body>
可以看出父盒子因为没有高度,子盒子设有高度,但是父盒子box实际高度还是为 0
②.触发了BFC特性的父盒子,会将子盒子的高度计入 --> 父盒子被撑开了
五、重提 body 作为父元素的 BFC 问题
1、body这个元素比较特殊,作为一个大容器,是不是默认创建了 BFC 呢,提出这个问题是因为我在写一个固定定位搜索框时发现多了一莫名的上边间隙,考虑到了是不是给 body 创建BFC,就可以避免,但也没有成功,百度搜索又有人说body创建了的,就纳闷了,先看问题:
<style type="text/css">
.box{
position: fixed;
width: 200px;
height: 200px;
background-color: pink;
}
.test{
width: 200px;
height: 200px;
background-color: green;
margin-top: 50px;
}
</style>
<body>
<div class="box"></div>
<div class="test"></div>
</body>
①.固定定位盒子box因脱标会压住下面同样大小的test盒子,但是下面test盒子使用了 margin-top 产生了上外边距后,却导致了固定定位的盒子也往下移了,一起下移,并还是覆盖着
问题产生:body默认不触发BFC,所以与test盒子外边距重叠了,导致body下移影响固定定位
②.给body加上触发BFC的条件:overflow:hidden; 再看问题就大了,直接给body元素加上 overflow:hidden无法触发BFC,结果还是一样的
③.给html和body都加上 overflow:hidden; 结果又能够正常触发BFC,消除了body重叠间隙
2、探究只给 body 元素添加 overflow:hidden; 无法触发BFC,而html、body同时添加才触发的原因,我们先来看 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:hidden的标准:
1、UAs must apply the 'overflow' property set on the root element to the viewport.
2、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'.
3、The 'visible' value when used for the viewport must be interpreted as 'auto'.
4、The element from which the value is propagated must have a used value for 'overflow' of 'visible'.
解释:
①、UAs 一定会将根元素上的 overflow 属性应用到视口上
②、当根元素是 html 元素,且这个根元素 overflow 为 visible(默认值本就是visible),而这个根元素有 body 元素作为其子元素,UA一定会将第一个 body 上的 overflow 属性应用于视口
③、用于视口的 overflow:visible; 将被解析为 overflow: auto
④、从中传播值的元素必须具有 "可见" 的 "溢出" 使用值(说明:这里可传播值的元素 body 的使用值将会变成 overflow:visible)
最终结论:
1. 给 body 加上 overflow:hidden; 是无法触发 BFC 的,(②)--> 因为 body 的 overflow:hidden 会被扩散到视口,(④)--> 最终使用值为 overflow: visible。
2. 给 html 和 body 同时加上 overflow:hidden; 正常触发BFC,(②)--> 作为根元素的 html 其 overflow 并不为 visible(我给设定了 hidden),则不满足条件②,便不会让其子元素 body 上的 overflow 扩散到视口,(①)--> 而是将 html 上的 overflow:hidden 应用到视口,因此触发了 BFC
3. 给 body 加上 overflow:hidden 之外的触发 BFC 条件,如 display:table、display:inline-block、position:absolute,这些不会引发 overflow 扩散行为 ,所以都会正常创建 BFC
其实还有更多关于扩散视口要注意的问题需要注意,这里不叙述了