# CSS的上下文之BFC
看到这个名词,可能会有些陌生,但其实 上下文 = 区域,如果这么理解的话就会有行级上下文、块级上下文、flex上下文等等有一定排列规则的区域,我们今天只聊一聊 块级格式化上下文(BFC)
# 一、什么是BFC?
BFC全称”Block Formatting Context”, 中文为“块级格式化上下文”。是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
下列方式会创建块格式化上下文(列举常见的方式):
- 根元素(
<html>
) - 浮动元素(元素的
float
不是 none) - 绝对定位元素(元素的 position 为 absolute 或 fixed)
- display 为 inline-block、table-cells、flex
- overflow 计算值不为 visible 的块元素
块格式化上下文包含创建它的元素内部的所有内容。
整理一下:
BFC属于普通的文档流,具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,它有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
# 二、BFC的特点以及应用
# 2.1 同一个BFC下,外边距会发生折叠
来看这样一段代码:
.box{
width: 300px;
}
.child{
margin: 100px;
width: 100px;
height: 100px;
background: rgb(95, 172, 182);
}
<div class="box">
<div class="child"></div>
<div class="child"></div>
</div>
现象:
明明两个child都存在100px的外边距,但他们实际间隔却不是200px,而是100px,这算是一种合并“规则”,当你发现你的页面因为加入了margin而出现了奇怪的问题,不妨往合并的方向思考
解释:
同一个BFC中,相邻的兄弟元素之间的相对的margin-bottom和margin-top会进行合并,并且显示的是较大值。
解决与注意:
想要解决这样的问题,我们可以通过将两个child放置于不同的BFC中,直接上图:
下图通过BFC解决了问题,是否产生了新的问题?是否可以通过其他方式解决呢?希望大家能灵活选择噢~
# 2.2 解决父子元素之间margin塌陷问题
来看这样一段代码:
body{
background: #ccc;
}
.box{
margin: 100px;
width: 300px;
height: 300px;
background: rgb(149, 98, 98);
}
.child{
margin: 50px;
width: 100px;
height: 100px;
background: rgb(95, 172, 182);
}
<div class="box">
<div class="child"></div>
</div>
现象:
- box元素存在外边距100px,相对于body的效果生效了,毫无疑问;
- child元素存在外边距50px,相对于box的效果仅左侧生效了,存在疑问;
解释:
有了2.1小节的经验,大家会猜测是不是margin再次发生了合并?也可以,但更合理的形容叫 “margin塌陷”。
父子相邻嵌套的元素在垂直方向的margin会发生塌陷,并取最大值。
拿例子中的box元素
举例,box作为顶,子元素向外称起50px却失效了,可以理解为顶塌陷了。
如果子元素的margin-top = 200px 会发生什么呢?
解决与注意:
通过触发BFC,你可以解决当下的问题,但是请思考,子元素的是否需要margin来实现间距,给box元素添加padding会不会更好一些?
# 2.3 BFC 可以包含浮动的元素(清除浮动)
我们都知道,浮动的元素会脱离普通文档流,来看下下面一个例子:
.box{
border: 1px solid black;
}
.child{
width: 100px;
height: 100px;
background: #ddd;
float: left;
}
<div class="box">
<div class="child"></div>
</div>
现象:
- child因为浮动,脱离了文档流;
- box盒子的高度只计算了border;
解释:
- 因为子元素已经脱离了文档流,所以父元素在计算高度时忽略了它;
解决:
触发容器的 BFC,使得容器包裹着浮动元素。
# 2.4 BFC 解决文字环绕的问题
浮动的目的。最初时,浮动只能用于图像(某些浏览器还支持表的浮动),目的就是为了允许其他内容(如文本)“围绕”该图像。而后来的CSS允许浮动任何元素。
body {
padding: 100px;
}
.box {
border: 1px solid black;
width: 300px;
background: #ddd;
}
.left {
width: 100px;
height: 100px;
float: left;
background: rgb(81, 196, 204);
}
<div class="box">
<div class="left"></div>
<div class="right">
解决文字环绕的问题, 解决文字环绕的问题, 解决文字环绕的问题, 解决文字环绕的问题
解决文字环绕的问题, 解决文字环绕的问题, 解决文字环绕的问题, 解决文字环绕的问题
</div>
</div>
现象:
- 给左侧子元素设置了左浮动,使得文字环绕在它周围,但为什么文字会被环绕,而不是被遮挡?
解释:
看到float会脱离文档流,这是相对于盒子模型来说的。但它没有脱离文本流。
- 文档流是相对于盒子模型讲的
- 文本流是相对于文子段落讲的
元素浮动之后,会让它脱离文档流,也就是说当它后面还有元素时,其他元素会无视它所占据了的区域,直接在它身下布局。但是文字却会认同浮动元素所占据的区域,围绕它布局,也就是没有脱离文本流。
在MDN上提到 (opens new window),该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性(与绝对定位相反)。
解决
将包裹文字的元素置为BFC,看图:
问题解决了,新知识又增加了,例如自适应两栏布局,请看下图:
# 写在最后
《CSS基础系列》第四篇文章
如果对你有所帮助不妨给本项目的github 点个 star (opens new window),这是对我最大的鼓励!
关于我
- 花名:余光
- WX:j565017805
- 沉迷 JS,水平有限,虚心学习中
其他沉淀