引言
本次讨论将深入探讨BFC(Block Formatting Context,块级格式化上下文)的几条核心规则,根据具体例子解释它们的用法。
盒模型
在了解BFC之前,我们先来理解一下盒模型。
一个盒子是由content、padding、border、margin组成的。
有两种不同的盒模型:标准盒模型和怪异盒模型。
两种盒模型由CSS中的box-sizing属性来控制
- 标准盒模型(content-box) 标准盒模型就是默认的盒模型。标准盒模型,元素的宽度和高度仅包括内容区域,不包含内边距、边框和外边距,这些部分会额外增加元素的实际尺寸。
- 怪异盒模型(border-box) 怪异盒模型将宽度和高度应用到内容、内边距和边框的总和上。
在下面的代码中,我们将box1为默认状态,box2设置怪异盒模型,box3设置标准盒模型。宽高都设置为100px。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一个盒子,自己的规则</title>
<style>
*{
margin: 0;
padding: 0;
}
/* 盒模型 + 块级 */
.box1,.box2,.box3 {
width: 100px;
height: 100px;
padding: 10px;
border: 1px solid red;
background-color: green;
}
.box2 {
/* border 以内盒子的大小 IE 怪异盒模型 */
box-sizing: border-box;
}
.box3 {
/* 默认值,标准盒模型 w h content大小 */
box-sizing: content-box;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
可以看到,box1和box3都是变成了122px122px,因为他们都是content-box,宽高为content的大小。而box2为border-box,是100px100px,它以border作为宽高
元素分类
根据元素默认的显示行为,可以将元素分为两大类:块级元素(Block-level Elements) 和 行内元素(Inline Elements) 。
- 块级元素独占一行,可以设置宽高,支持所有的外边距、内边距和边框属性。
- 行内元素与其他行内元素在同一行内流动显示,直到遇到块级元素或行宽不够时才会换行。只有水平方向的内边距和边框会对布局产生影响。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
border: 1px solid red;
padding: 10px 20px;
display: inline;
}
span {
width: 100px;
height: 100px;
display: block;
background-color: green;
}
</style>
</head>
<body>
<div>123</div>
<span>11</span><span>222</span>
</body>
</html>
行内元素设置的宽高并没有生效,并且设置的垂直方向的内边距和边框也没有对下面的块级元素产生影响。
BFC - 块级格式化上下文
什么是BFC?
BFC(Block Formatting Context,块级格式化上下文) 是Web页面中一个独立的渲染区域。在这个区域内,元素按照特定规则进行布局,并且该区域内的元素不会受到外部元素的影响,也不会影响外部元素的布局。BFC在潜移默化的影响着页面的布局。
创建新的BFC
创建新的BFC有以下几个条件:
- 根元素 (
<html>)会创建一个BFC - 浮动元素 (
float不为none) - 绝对定位
- 固定定位元素 (
position为absolute或fixed) - 行内块容器 (
display为inline-block) - 表格单元格 (
display为table-cell) 和表格标题 (display为table-caption) overflow属性(除visible之外)- 弹性盒子 (
display: flex或inline-flex) 也被称为FFC - 网格布局 (
display: grid或inline-grid) 也被称为GFC - 多列容器 (
column-count或column-width不为auto)
BFC的规则
我在这里直接列出了BFC的规则,在下面的代码中将解释这些规则。
- block level box 垂直方向,一个接一个的放置
- 盒子垂直方向的距离由margin决定,同一个BF相邻盒子margin会重叠,大的说了算
- 每个元素的margin 左边,与包含块(父元素)border的左边相接触,即使存在浮动也会忽略浮
- BFC 区域不会与float box 重叠
- 独立渲染区域,不受外界影响(内部也不受外部影响)
- 计算BFC的高度时,浮动元素也参与计算
block level box 垂直方向,一个接一个的放置
第一条原则。这也是为什么块级元素会独占一行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.div1,.div2{
width: 100px;
height: 100px;
}
.div1 {
background-color: red;
}
.div2 {
background-color: green;
}
</style>
</head>
<body>
<div class="div1"></div>
<div class="div2"></div>
</body>
</html>
盒子垂直方向的距离由margin决定,同一个BFC相邻盒子margin会重叠
第二条原则。我们给上面的盒子设置下外边框50px,下面的盒子设置上外边框30px。可以看到,最后得到的结果中,两个盒子之间并不是80px,而是50px。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC</title>
<style>
*{
margin: 0;
padding: 0;
}
.box {
width: 200px;
height: 200px;
background-color: lightblue;
border: 1px solid #000;
}
.box1 {
margin-bottom: 50px;
}
.box2 {
margin-top: 30px;
}
</style>
</head>
<body>
<div class="box box1">Box1</div>
<div class="box box2">Box2</div>
</body>
</html>
因为它们处在同一个BFC之中,外边框重叠了。
有三种情况:
- 如果两个都是正值,实际距离取较大值
- 如果一个正一个负,取差值
- 如果两个都为负,取绝对值最大的 所以为了实现想要的效果,我们要把它们放在不同的BFC中,创建一个新的BFC就能够让它们之间的间距为80px了。
<div class="box box1">Box1</div>
<!-- 开启新的格式化上下文 -->
<div style="overflow:hidden;"></div>
<div class="box box2">Box2</div>
每个元素的margin左边,与包含块(父元素)border的左边相接触,即使存在浮动也会忽略浮
第三条原则。还是拿上面的例子,给Box1和Box2添加左外边框。可以看到,margin左边紧贴父元素的border。(例子中已经清除了默认的外边框和内边框)
BFC 区域不会与float box 重叠
第四条原则。在我们使用浮动后,元素将会脱离文档流。 没加BFC之前。在同一个BFC下,重叠。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
.container {
border: 2px solid #000;
padding: 10px;
overflow: hidden;
}
.float-left {
float: left; /* Formatting context */
width: 150px;
height: 100px;
background-color: lightblue;
margin: 10px;
}
.margin-box {
width: 200px;
height: 100px;
background-color: lightgreen;
margin: 20px 0 20px 50px;
}
</style>
</head>
<body>
<div class="container">
<div class="float-left">这是一个左浮动的元素</div>
<div class="margin-box">这是有左侧外边距的盒子这是有左侧外边距的盒子这是有左侧外边距的盒子</div>
</div>
</body>
</html>
添加BFC之后,就不会重叠了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
border: 2px solid black;
padding: 10px;
}
.float-box {
float: left;
width: 150px;
height: 100px;
background-color: lightblue;
margin: 10px;
}
.bfc-box {
width: 300px;
height: 100px;
background-color: lightgreen;
overflow: hidden;
/* 创建 BFC */
}
</style>
</head>
<body>
<div class="container">
<div class="float-box">这是一个左浮动的盒子</div>
<div class="bfc-box">这是一个创建了 BFC 的盒子</div>
</div>
</body>
</html>
在这里使用 overflow: hidden;创建BFC,这也是常用的清除浮动的方法。
独立渲染区域,不受外界影响(内部也不受外部影响)
第五条原则。外界的浮动并没有影响下一个BFC中的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
border: 2px solid black;
padding: 10px;
}
.float-box {
float: left;
width: 150px;
height: 100px;
background-color: lightblue;
margin: 10px;
}
.bfc-box {
width: 300px;
height: auto;
background-color: lightgreen;
overflow: auto; /*创建 BFC 切换*/
padding: 10px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="container">
<div class="float-box">这是一个左浮动的盒子</div>
<div class="bfc-box">
<p>这是创建了 BFC 的盒子内部的内容。</p>
<p>注意,这个内容不会被外部的浮动元素影响。</p>
</div>
</div>
</body>
</html>
计算BFC的高度时,浮动元素也参与计算
第六条原则。当父元素没有设置高度或者设置了最小高度,但子元素的高度大于父元素的高度,子元素又设置的浮动。父元素高度塌陷。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 而用 BFC 清除浮动的原理就是:计算 BFC 的高度时,浮动元素也参与计算。只要触发父元素的 BFC 即可。 */
.parent {
background-color: red;
overflow: hidden;
}
.child {
float: left;
height: 200px;
width: 200px;
background-color: green;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
如果没有设置BFC清除浮动将会是这样,父元素塌陷。
创建BFC之后,浮动元素也参与父元素的高度计算,把父元素撑起来了。
结语
综上所述,理解BFC及其工作机制对于掌握CSS布局原理和解决复杂的页面布局问题至关重要。BFC对于清除浮动和解决某些布局问题非常有用。通过合理地创建和利用BFC,开发者可以更精确地控制网页元素的排列和外观,避免不必要的样式冲突,从而构建更加稳健和高效的Web页面。
这就是BFC的全部内容了。时刻牢记BFC的几个规则。
都看到这了,麻烦点个赞呗!!!