前言
这个男人叫小帅,哦不,这个玩意叫BFC,虽然你可能不认识它,但是在你写HTML时,已经其实已经遵循它的“规则”办事了,当然除了BFC,我们还需要知道其他的“规则”,这样我们就更容易去布置好看的界面。
下面我们将深入探讨文档流、盒模型、显示类型转换、块格式化上下文(BFC)及其与其他格式化上下文(如弹性布局上下文FFC和网格布局上下文GFC)的关系,并通过具体代码示例来帮助理解。
文档流与布局基础
HTML文档中的元素按照从上到下、从左到右的方式自然排列,形成所谓的“文档流”。默认情况下,块级元素(例如<div>、<p>等)会垂直堆叠,而行内元素(如<span>、<a>等)则在同一行内水平排列。这种简单的排列方式构成了网页的基本布局框架。
代码:
<body>
<p>我是块级元素,我独占一行</p> <!-- 块级元素 -->
<p>我也是块级元素,我独占一行</p> <!-- 块级元素 -->
<span>我是行内元素</span><span>我也是行内元素</span> <!-- 行内元素 -->
</body>
图示:
了解上面这些,你是否有疑问呢?块级就一定是块级吗?行内元素就一定是块级吗?能否转换呢?
显示类型与转换
元素的显示类型决定了它在文档流中的行为。主要分为:
- 块级元素 (
block) :占据一行并可以设置宽高。 - 行内元素 (
inline) :不打断文本流且不能直接设定宽度或高度。
比如:
<!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;
background-color: green;
display: block;
}
</style>
</head>
<body>
<div>我是块级元素</div>
<span>我是行内元素</span>
<span>我也是行内元素</span>
</body>
</html>
图示:
通过CSS
display属性,可以改变元素的显示类型,我们这个例子中,就将块级变成了行内元素,行内变成块级元素,
- 行内元素的长宽大小不能设置,由内容支撑,
- 而块级元素的长宽是可以直接设置的
下面我们来看看盒子模型:
盒模型与尺寸计算
每个HTML元素都被视为一个矩形盒子,它由内容区、内边距(padding)、边框(border)和外边距(margin)组成。根据CSS规范,有两种不同的盒模型:
- 标准盒模型 (content-box) :宽度和高度仅适用于内容区域,默认为标准盒模型。
- IE盒模型 (border-box) :宽度和高度包括了内容、内边距和边框。
可以通过设置box-sizing属性来选择使用哪种盒模型:
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一个盒子,自己的规则</title>
</head>
<style>
/* 盒模型 + 块级 */
.box,.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>
<body>
<div class="box"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
图示:
结果:
由图可知,在其他相同的前提下,因为设置了不同的
box-sizing,得到了两个不同的盒模型,两种盒模型的计算规则如下:
- 标准盒模型 (content-box)
- 实际宽度 =
width+padding-left+padding-right+border-left-width+border-right-width - 实际高度 =
height+padding-top+padding-bottom+border-top-width+border-bottom-width
- 实际宽度 =
- IE盒模型 (border-box)
-
内容宽度 =
width- (padding-left+padding-right+border-left-width+border-right-width) -
内容高度 =
height- (padding-top+padding-bottom+border-top-width+border-bottom-width)
-
深入BFC之中
在HTML文档中,根元素(即<html>标签)本身就是一个顶级BFC,它为整个页面提供了一个基本的布局框架。就像建筑中的地基一样,这个顶级BFC确保了页面内的所有内容都遵循一定的布局规则。具体的元素排列和布局则由更细致的CSS属性控制,如浮动、定位和弹性盒子等。因此,即便你不显式地创建BFC,实际上也在利用BFC的基本特性来组织页面内容。
那么BFC有什么用,能干什么,怎么创建BFC呢?
我的这个文章有讲到作用和创建: 当CSS中子元素浮动起来后导致父元素高度为空,该怎么解决?😬😬=-=在课堂上,老师提到了关于父元素高度塌陷的问题。现 - 掘金
现在我来补充一下:
重叠的易错点:
代码:
这段代码创建了的BFC,实现了边距不重叠的作用。
案例一:
<!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 red;
}
.box1{
margin-bottom: 50px;
}
.box2{
margin-top: 30px;
}
</style>
</head>
<body>
<div class="box box1">Box1</div>
<div style="overflow: hidden;">
<div class="box box2" ></div>
</div>
</body>
</html>
案例二:
当我们小小的更改一下,将样式写入box2中时,创建这个新的BFC,对于防止边距的重叠就没有起到作用。你知道为什么吗?
<body>
<div class="box box1">Box1</div>
<div class="box box2" style="overflow: hidden;"></div>
</body>
案例分析:
案例二中:
尽管为.box2添加了overflow: hidden来创建新的BFC,但由于.box1和.box2依然是相邻的兄弟元素,并且它们同属一个父级BFC(即<body>),因此它们之间的外边距仍然会发生折叠。
案例一中:
通过将.box2放入一个新的容器并在该容器上设置overflow: hidden,我们创建了一个新的BFC。这样做的好处是,.box1和.box2不再处于同一个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>
<p>注意,这个内容不会被外部的浮动元素影响。</p>
<p>注意,这个内容不会被外部的浮动元素影响。</p>
<p>注意,这个内容不会被外部的浮动元素影响。</p>
<p>注意,这个内容不会被外部的浮动元素影响。</p>
</div>
</div>
</body>
</html>
创建独立的渲染区域(BFC)
通过设置 .bfc-box 的 overflow: auto;,创建了一个新的BFC。这意味着:
- 隔离内部布局:
.bfc-box内部的元素布局与外部元素完全隔离,不受外部浮动元素的影响。 - 防止浮动溢出:即使
.float-box是一个浮动元素,它也不会超出.bfc-box的边界,确保父容器能够正确包裹浮动元素。
图解:
这就是有没有BFC是区别所在
BFC的亲朋好友:GFC、FFC
我们简单介绍一下GFC和FFC:
GFC
是CSS Grid布局的一部分,它定义了一个新的块级格式化上下文,类似于BFC(Block Formatting Context),但专门为网格布局设计。当一个元素被设置为display: grid或display: inline-grid时,它就会创建一个新的GFC,在这个上下文中,子元素(即网格项)将遵循CSS Grid布局规则进行排列。
简单用法:
<!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;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto; /* 三列等宽 */
gap: 10px; /* 单元格之间的间隔 */
padding: 10px; /* 网格容器的内边距 */
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 30px;
text-align: center;
}
.item1 { background-color: red; }
.item2 { background-color: orange; }
.item3 { background-color: yellow; }
.item4 { background-color: green; }
.item5 { background-color: blue; }
.item6 { background-color: indigo; }
.item7 { background-color: violet; }
.item8 { background-color: pink; }
.item9 { background-color: brown; }
</style>
</head>
<body>
<div class="grid-container">
<div class="grid-item item1">1</div>
<div class="grid-item item2">2</div>
<div class="grid-item item3">3</div>
<div class="grid-item item4">4</div>
<div class="grid-item item5">5</div>
<div class="grid-item item6">6</div>
<div class="grid-item item7">7</div>
<div class="grid-item item8">8</div>
<div class="grid-item item9">9</div>
</div>
</body>
</html>
FFC
是CSS中一种用于布局的上下文,它由设置了display: flex或display: inline-flex属性的容器创建。在这种上下文中,直接子元素被称为“弹性项”(flex items),它们会遵循Flexbox布局规则进行排列和对齐。
下面是一个简单的例子:
<!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;
}
.flex-container {
display: flex;
justify-content: space-around; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 300px; /* 容器高度 */
background-color: lightgray;
}
.flex-item {
width: 100px;
height: 100px;
background-color: tomato;
margin: 5px;
text-align: center;
line-height: 100px; /* 让文本垂直居中 */
color: white;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
</html>
最后:
本文讲的有点杂乱,得结合之前的一篇文章,就当作是我最近学习的总结。 如果有问题也请指出,谢谢。