区块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
1. 背景介绍
我们常常说文档流的时候其实分为定位流、浮动流和普通流三种。其中普通流就是指BFC中的FC。FC是formatting context的首字母缩写,直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。
常见的FC有BFC、IFC,还有GFC和FFC。BFC是block formatting context,也就是块级格式化上下文,是用于布局块级盒子的一块渲染区域。
2. 知识剖析
一:BFC是什么
BFC是可视化CSS渲染网页的一部分,它是一个区域,块级布局,相互浮动在这个区域发生。
一个BFC块区域包含所有里面的元素,除子元素创建了新的BFC。(因为各个BFC是一个独立的区域,BFC之间相互不影响)。
所以,由于html(根元素)是独立的BFC,在里面的浮动,块级布局等才会相互影响,若新创建BFC,则相邻BFC之间的浮动元素,或是其他元素将不会影响。如,相邻两个块级元素的外边距折叠的情况将不会发生。
参考文献:深入理解BFC - 博客园 | BFC (Block formatting context)是什么? - 博客园
二:触发条件
满足下列条件之一就可触发BFC(造成元素变成BFC布局的原因):
【1】文档的根元素,即HTML元素
【2】浮动元素,即float的值不为none的元素
【3】绝对定位元素,即position 值为 absolute 或 fixed 的元素
【4】行内块元素(display 值为 inline-block 的元素)。
【5】表格单元格(display 值为 table-cell,HTML 表格单元格默认值)。
【6】表格标题(display 值为 table-caption,HTML 表格标题默认值)。
【7】contain 值为 layout、content 或 paint 的元素。
【8】overflow值不为visible 或 clip 的块级元素。
【9】display的值为flow-root的元素。 ——display:flow-root不干别的,专门用来触发BFC。
【10】弹性元素(display 值为 flex 或 inline-flex 元素的直接子元素),如果它们本身既不是弹性、网格也不是表格容器。
【11】网格元素(display 值为 grid 或 inline-grid 元素的直接子元素),如果它们本身既不是弹性、网格也不是表格容器。
格式化上下文影响布局,通常,我们会为定位和清除浮动创建新的 BFC,而不是更改布局,因为它将:●包含内部浮动。 ●排除外部浮动。 ●阻止外边距重叠。
备注: 弹性 / 网格容器(display:flex/grid/inline-flex/inline-grid)建立新的弹性/网格格式化上下文,除布局之外,它与区块格式化上下文类似。弹性/网格容器中没有可用的浮动子级,但排除外部浮动和阻止外边距重叠仍然有效。
总结:CSS触发BFC(Block Formatting Context ——块格式化上下文)的方法主要包括以下几种
-
根元素:根元素(即
<html>
元素)自身就是一个BFC。 -
浮动元素:当元素的
float
属性值不为none
时,即设置为左浮动或右浮动,这样的元素会触发BFC。 -
绝对定位元素:当元素的
position
属性值为absolute
或fixed
时,这样的绝对定位元素会触发BFC。 -
行内块元素:当元素的
display
属性值为inline-block
时,这样的行内块元素会触发BFC。 -
表格单元格和表格标题:当元素的
display
属性值为table-cell
或table-caption
时,这样的表格单元格和表格标题也会触发BFC。 -
弹性盒子容器:当元素的
display
属性值为flex
、inline-flex
、grid
或inline-grid
时,这样的弹性盒子容器和网格容器会触发BFC。 -
overflow属性:当元素的
overflow
属性值不为visible
时,如设置为auto
、scroll
或hidden
,这样的元素也会触发BFC。
这些方法涵盖了CSS中触发BFC的主要方式,包括通过元素的特定属性设置来创建BFC,从而影响布局和样式表现。
三:BFC的作用
资料参考:BFC是啥?display: flow-root是啥?-CSDN博客
● 包含浮动元素(清除浮动)——父元素包裹住子元素
BFC会根据子元素的情况自适高度,这个特性是对父元素使用overflow:hidden/auto/scroll、 float:left/right 样式可以闭合浮动的。
用 BFC 包住浮动元素,儿子是浮动元素,正常情况下,浮动元素会脱离文档流离开爸爸的怀抱。但是BFC的功能就是不让儿子跑出爸爸的怀抱。
● 不被浮动元素覆盖——兄弟元素之间划清界限
浮动元素会无视兄弟元素的存在, 覆盖在兄弟元素的上面, 为该兄弟元素创建BFC 后可以阻止这种情况的出现。
四:BFC的规则
资料参考:bfc规则详解_-CSDN博客
● 内部的Box会在垂直方向,一个接一个地放置。 就是我们平常div一行一行块级放置的样式。Box垂直方向的距离由margin决定。
● 属于同一个BFC的两个相邻Box的margin会发生重叠。
● 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。就是元素左margin和包含块左border接触,即使存在浮动也是如此。左浮动就是靠左,右浮动就是靠右,
● BFC的区域不会与外部的float box重叠。应用于两列布局
● BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之,也如此。上下margin不影响,浮动不覆盖。
● 计算BFC的高度时,浮动元素也参与计算,也就是说,在BFC内部的浮动元素也计算在BFC的宽度之内。如父元素高度塌陷,清除浮动。父元素高度由内部撑开,计算BFC高度,内部浮动的子元素也参加。
3. 常见问题
1. 外边距折叠(Collapsing Margins)。
2. 让一个没有设置高度的容器包含浮动元素。
3. 阻止文字环绕。
4. 解决方案
1. 外边距折叠
外边距折叠有很多种情况,最简单的就是上下两个盒子,上面的设置了margin-bottom,下面的设置了margin-top,这时候总的外边距并不是两者相加,而是取最大的外边距作为总的外边距。(假设外边距的设置为正值)
下面的代码发生了外边距折叠。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>外边距折叠</title>
<style>
.container {
background-color: red;
width: 400px;
}
p {
font-size: 30px;
background: yellow;
margin: 100px 0;
}
</style>
</head>
<body>
<div class="container">
<p>盒子1</p>
<p>盒子2</p>
</div>
</body>
</html>
发生了外边距折叠(上)
下面的代码通过使用overflow: hidden;新创建一个BFC,从而实现阻止外边距折叠。(overflow: hidden;意思是:如果盒子的内容超出盒子,则这部分内容隐藏。)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>外边距折叠</title>
<style>
.container {
background-color: red;
width: 400px;
}
p {
font-size: 30px;
background: yellow;
margin: 100px 0;
}
.bfc {
overflow: hidden;
}
</style>
</head>
<body>
<div class="container">
<p>盒子1</p>
<div class="bfc">
<p class="bfc">盒子2</p>
</div>
</div>
</body>
</html>
使用BFC阻止外边距折叠(下)
2. 容器无高度包含浮动元素
无BFC,容器无高度包含浮动元素会产生如下效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>容器无高度包含浮动元素</title>
<style>
.container {
background-color: red;
width: 400px;
outline: 1px dashed red;
margin-top: 10px;
}
p {
font-size: 30px;
background: yellow;
margin: 100px;
float: left;
}
</style>
</head>
<body>
<div class="container">
<p>盒子1</p>
<p>盒子2</p>
</div>
</body>
</html>
高度坍塌现象
可以看到,由于浮动元素是脱离普通文档流的,所以.container盒子发生了塌陷,高度变为0。如何阻止这种情况发生呢,可以给上面的代码.container盒子添加了一条样式overflow: hidden,解决了容器盒子塌陷的问题。
效果图如下:
3. 阻止文字环绕
左图右文,文字环绕图片,效果图:
代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文字环绕图片</title>
<style>
.container {
width: 600px; /* 容器宽度 */
margin: 20px auto; /* 居中显示 */
}
.float-left {
float: left; /* 图片向左浮动 */
margin-right: 15px; /* 图片右侧留白 */
margin-bottom: 10px; /* 图片下方留白 */
width: 200px; /* 控制图片宽度 */
height: auto; /* 高度自适应 */
}
</style>
</head>
<body>
<div class="container">
<img src="nuidc.jpg" alt="示例图片" class="float-left" />
<p>
这里是一段示例文字,它将会环绕在图片的周围。你可以根据需要添加更多的文字内容,看看文字是如何环绕图片布局的。文字会根据图片的位置和大小自动调整排列,以适应页面的布局。
效果说明 1. 浮动方向:图片设置为 float: left 后,会脱离文档流并向左浮动,文字会自动环绕在图片右侧。 2. 间距控制:通过 margin-right 和 margin-bottom 在图片周围创建空隙,避免文字紧贴图片。 3. 容器宽度:父容器设置固定宽度可防止布局溢出。
注意事项 1. 清除浮动:如果浮动图片后还有其他非浮动内容,可能需要用 clear: both 清除浮动。 2. 响应式设计:建议为图片设置 max-width: 100% 和 height: auto 实现自适应。 3. 图文间距:根据设计需求调整 margin 值,推荐使用 em 或 rem 单位。
最终效果:文字会紧密围绕在图片周围,类似杂志排版样式。
</p>
</div>
</body>
</html>
有时候我们不需要文字环绕,就想让文字老老实实待在右边,这时我们可以加入.text { overflow: hidden;}
效果如下:
4. 扩展思考
为什么用overflow触发而不用其他的?
因为其他如:float,positon等等会影响布局,达不到我们想要的效果。
5. 更多讨论
1. 什么是IE的haslayout?
hasLayout可以简单看作是IE5.5/6/7中的BFC(Block Formatting Context)。也就是一个元素要么自己对自身内容进行组织和尺寸计算(即可通过width/height来设置自身的宽高),要么由其containing block来组织和尺寸计算。
而IFC(即没有拥有布局)而言,则是元素无法对自身内容进行组织和尺寸计算,而是由自身内容来决定其尺寸(即仅能通过line-height设置内容行距,通过行距来支撑元素的高度;也无法通过width设置元素宽度,仅能由内容来决定而已)
2. overflow的auto还是visible可以触发bfc?
auto,hidden,scroll可以触发
3. 利用浮动再触发bfc用来干嘛?
用来实现左列定宽,右列自适应布局
参考资料
—— CSS | 详解何为BFC以及BFC能解决什么问题 - CSDN博客 ——
深入理解BFC - 小火柴的蓝色理想 - 博客园 | BFC (Block formatting context) 是什么 - 博客园
BFC是啥?display: flow-root是啥?-CSDN博客
display - CSS:层叠样式表 | MDN | display 的新属性值 flow-root
BFC--块级格式化上下文-CSDN博客 | 学习块格式化上下文(BlockFormattingContext) - 简书
关于元素间的边距重叠问题与BFC-腾讯云开发者社区 | 理解CSS布局和BFC - 前端开发社区
如何理解块级格式化上下文BFC(block formatting context) - 知乎 | 深入理解 BFC - 知乎