# 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,水平有限,虚心学习中

其他沉淀

Last Updated: 1/31/2023, 12:19:55 PM