这是我参与「第四届青训营 」笔记创作活动的第7天
「前言」
「什么是 BFC」
bfc:Block Formatting Context,即 块级-格式-上下文
引用W3C的官方解释:
BFC它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context提供了一个环境,HTML在这个环境中按照一定的规则进行布局。
是不是听起来一头雾水
要想理解 bfc,首先就要理解什么是 上下文,把它联想为 js 里面的 上下文,换句话说也就是在一个作用域,作用域划分了变量的执行环境,也就是起到 隔离 的作用,同理。那么 bfc 也就是创建一个对于 html 来说的隔离外界的 作用域,在这个作用域中享受着 bfc 提供的规则。
「BFC 布局规则」
bfc 是对具有 block-level box 块级属性 的元素才有的特性(这个块级元素即可以 display: block | list-item | table),可以把 bfc 理解为块级元素可以设置的属性,一旦设置这个 bfc 的属性,就生成响应的规则
- 内部的
Box会在垂直方向,一个接一个地放置。 - Box垂直方向的距离由margin决定。属于同一个
BFC的两个相邻Box的margin会发生重叠 - 每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。- 计算
BFC的高度时,浮动元素也参与计算
「如何触发 BFC 」
就像前文说的一样 bfc 是可以块级元素的一个可以设置的属性,但也不是普通的属性,需要通过其他的方式来触发
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
「实例讲解 BFC」
光说不练假把式,直接上代码
场景:让一张图片和一段文字在一行显示
<style>
img,
p {
border: 3px solid #000;
}
</style>
</head>
<body>
<div>
<img src="./图片1.jpg" alt="">
<p>bfc</p>
</div>
</body>
基本的样式
<style>
img,
p {
border: 3px solid #000;
}
img {
float: left;
margin-left: 20px;
}
</style>
</head>
<body>
<div>
<img src="./图片1.jpg" alt="">
<p>bfc</p>
</div>
</body>
让 img 浮动,同时设置 margin 为了能更好的看到效果
给img 设置了浮动也触发了 bfc
每个元素的
margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
这里就会发现,
p 标签的高度和宽度都不是我们想要的,实际效果为 p 标签填充剩余区域的地方,而且高度和图片等高,而且最外层的 div 高度是由 p 控制的,那我们想让他由 p 和 img 中最高的来控制。
原因:给 img 设置浮动会脱离文档流,所以 div 高度是由 p 控制的。
那怎么解决呢,这时候就要请出 bfc 了,前文说它是块级元素的一个特殊的属性,那我们可以把这个属性添加在一个 类 上,那块级元素想要添加 bfc 这个属性,其实转换为添加一个 类名,我们使用一个可以触发 bfc 的规则创建
.bfc {
overflow: hidden;
}
给最外层第 div 添加 bfc
<body>
<div class="bfc">
<img src="./图片1.jpg" alt="">
<p>bfc</p>
</div>
</body>
这时候 div 的高度确实是由 p 和 img 中最高的来控制
原因:给 div 设置了 bfc,相当于给 p 和 img 划分了一个作用域,自然 div 的高度就被撑开了,利用了 bfc 的布局规则:
计算
BFC的高度时,浮动元素也参与计算
但是还有一个问题,p 的长宽还没处理成我们想要的样子
如果给 p 也设置一个 bfc 看看会怎么样
<body>
<div class="bfc">
<img src="./图片1.jpg" alt="">
<p class="bfc">bfc</p>
</div>
</body>
为什么给 p 设置一个 bfc就可以解决呢?
原因:给 p 设置 bfc 也是给 p 设置了一块(独立的)作用域,不能延伸到图片的左边去,利用了布局规则:
BFC的区域不会与float box重叠。
最后的代码:
<style>
img,
p {
border: 3px solid #000;
background-color: #ccc;
}
img {
float: left;
margin-left: 20px;
}
.bfc {
overflow: hidden;
}
</style>
</head>
<body>
<div class="bfc">
<img src="./图片1.jpg" alt="">
<p class="bfc">bfc</p>
</div>
</body>
最后总结一下例子:
- 就如上面的例子,在给
div设置了bfc之后,整个div会解决原来浮动产生塌陷的状态,原理是bfc为了不影响外部元素的布局,而形成了自己独立的绘制区域,所以要计算浮动元素的高度。 - 给
p设置bfc,为了不影响内部的布局,会主动变窄让出原先被覆盖的位置。
「逃离 BFC」
bfc 既然有好处,那也肯定有坏处
解决几个常见的 bfc 的影响
块级元素垂直排列
<style>
.box {
width: 200px;
height: 200px;
margin-right: 0;
border: 3px solid #000;
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
</body>
即使给每个 box 添加 margin-right也不能使两个 box 在一行排布
原因:根级元素也出发了 bfc
内部的
Box会在垂直方向,一个接一个地放置。
解决办法:利用浮动的特性可以解决,或者使两个 box 变为 inline-block
多个 margin 重叠
<style>
.box {
width: 40px;
height: 40px;
border: 3px solid #000;
margin: 40px;
}
.container {
width: 300px;
height: 300px;
border: 3px solid #000;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>
</body>
两个 box 实际的距离不是两个两倍的 margin 值
原因:出发了 bfc 的规则:
Box垂直方向的距离由margin决定。属于同一个
BFC的两个相邻Box的margin会发生重叠
解决办法:利用 bfc的规则,使两个 bfc 不相邻,即可以用一个 div 包裹其中的 box
margin-top 传递
对上个例子进行改写
<style>
.box {
margin-top: 40px;
width: 40px;
height: 40px;
border: 3px solid #000;
}
.container {
width: 300px;
height: 300px;
background-color: pink;
/* border: 3px solid #000; */
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>
</body>
利用 bfc 解决:为 container 添加 bfc,原理利用以下规则
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
给 container 创建一块独立的区域,而不影响外部环境
「参考文章」
BFC神奇背后的原理_w3cschool
CSS 外边距(margin)重叠及防止方法 - 知乎 (zhihu.com),
推荐这篇文章,作者详解讲解关于 margin 重叠的规则
「结语」
通过写这篇文章的同时,发现 CSS 到处都是 bfc,学习bfc的同时,我们可以更好的利用 bfc 解决问题(清除浮动...)