在学习前端布局的时候,遇到了一个很重要的概念 ——BFC,感觉它特别神奇,就像是前端布局世界里的一个 “神秘容器”。与此同时,我又联想到了 FFC,这两者虽然名字里都带 “FC”,但其实是近亲关系,都属于 CSS 中的格式化上下文,只是各自掌管着不同的布局规则,在前端世界里发挥着独特的 “影响力”。
BFC
BFC,也就是 Block Formatting Context,中文叫块级格式化上下文。它就像是前端布局里的一个 “秘密武器”,拥有一套独特的布局规则,打造出一个独立的渲染区域。在这个区域内,元素们遵循着特定的规则进行排列,与区域外的元素互不干扰,仿佛拥有了自己的 “小世界”。
在弹性布局流行起来之前,float 可是布局的 “扛把子”,经常用来实现两列、三列甚至多列布局 。比如说,想做一个简单的两列布局,左边栏固定宽度,右边栏自适应。代码大概长这样:
.left {
width: 200px;
height: 100vh;
background-color: lightblue;
float: left;
}
.right {
width: calc(100% - 200px);
height: 100vh;
background-color: yellowgreen;
}
<div class="left"></div>
<div class="right"></div>
但是,float 有个让人头疼的问题,就是浮动元素会脱离文档流 。什么意思呢?就是它会 “跑” 出正常的文档排列顺序,导致一些布局上的混乱,比如父元素高度塌陷。看下面这段代码:
.container{
background-color: aqua;
}
.box{
width: 100px;
height: 100px;
background-color: red;
margin: 10px;
float: left;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
这里的.container是父元素,里面有三个浮动的.box子元素。由于浮动元素脱离了文档流,.container就没法正确计算高度,出现了高度塌陷,就好像父元素 “撑不起来” 了一样 。这时候,BFC 就派上用场啦!只要触发.container的 BFC,比如给它设置overflow: hidden,代码变成:
.container{
background-color: aqua;
overflow: hidden;
}
.container就升级成了一个 BFC “小王国” 。在 BFC 里,计算高度时会把浮动子元素也考虑进去 ,这样父元素就能正确 “包裹” 住子元素,解决高度塌陷问题。但是要注意,清除浮动是BFC的一个特性,而不是所有BFC触发方式都能清除浮动
除了清除浮动,BFC 还有很多厉害的地方。比如说,它能防止外边距重叠 。当两个相邻的块级元素处于同一个 BFC 中时,它们的垂直外边距会发生重叠。看下面这个例子:
.box1{
width: 100px;
height: 100px;
background-color: red;
margin-bottom: 20px;
}
.box2{
width: 100px;
height: 100px;
background-color: blue;
margin-top: 10px;
}
<div class="box1"></div>
<div class="box2"></div>
按照常理,.box1的margin-bottom是 20px,.box2的margin-top是 10px,它们之间的距离应该是 30px 。但因为处于同一个 BFC,实际两者间距是 20px,取了较大的margin-bottom值。如果不想让它们重叠,就可以把它们分别放在不同的 BFC 中。比如:
.box1{
width: 100px;
height: 100px;
background-color: red;
margin-bottom: 20px;
}
.container{
overflow: hidden;
}
.box2{
width: 100px;
height: 100px;
background-color: blue;
margin-top: 10px;
}
<div class="box1"></div>
<div class="container">
<div class="box2"></div>
</div>
通过给.box2的父元素.container设置overflow: hidden触发 BFC,让.box1和.box2分属不同 BFC,外边距就不会重叠了。
那怎么才能触发 BFC 呢?方法还挺多:
- 设置元素的
float属性值不是none,元素就会触发 BFC。 - 元素的
position属性值被设置为absolute或fixed时,也会触发 BFC。 - 当一个块元素的
overflow属性被设置为auto、scroll或hidden时(且该元素不是table或inline-table),同样会触发 BFC 。 display属性值为 inline-block、table-cell、flow-root 等可以触发 BFC。但是flex/inline-flex 会触发 FFC(弹性格式化上下文),而不是 BFC。
FFC
说完 BFC,再来讲讲 FFC。FFC 是 Flex Formatting Context 的缩写,也就是弹性格式化上下文 。它是随着 CSS3 的弹性布局(Flexbox)出现的,给我们布局带来了更多的灵活性。
当我们给一个元素设置display: flex或者display: inline-flex时,这个元素就会成为一个 FFC 容器 ,它里面的子元素(也就是 flex item)会按照弹性布局的规则来排列。
比如说,想让几个元素在一行水平排列,并且均匀分布,用 FFC 就很简单:
.flex-container {
display: flex;
justify-content: space-around;
width: 500px;
height: 150px;
background-color: lightpink;
}
.flex-item {
width: 80px;
height: 80px;
background-color: orange;
}
<div class="flex-container">
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>
这里的.flex-container因为设置了display: flex,变成了 FFC 容器 。justify-content: space-around这个属性让三个.flex-item在容器里均匀分布,左右两边的间距也很对称,效果立竿见影。
在 FFC 里,子元素默认是在一行排列的 。要是空间不够,它们不会自动换行,而是会缩小自己的宽度(除非设置了flex-shrink: 0)。如果想让它们换行,可以给容器加上flex-wrap: wrap属性。代码如下:
.flex-container {
display: flex;
flex-wrap: wrap;
width: 300px;
background-color: lightgreen;
}
.flex-item {
width: 80px;
height: 80px;
margin: 10px;
background-color: purple;
}
这样,当一行放不下所有的.flex-item时,它们就会自动换到下一行。
FFC 还有很多强大的属性,比如align-items可以控制子元素在交叉轴(默认是垂直方向)上的对齐方式 。如果想让子元素在垂直方向上居中,可以这样写:
.flex-container {
display: flex;
align-items: center;
height: 200px;
background-color: skyblue;
}
.flex-item {
width: 100px;
height: 100px;
background-color: yellow;
}
<div class="flex-container">
<div class="flex-item"></div>
</div>
通过设置align-items: center,.flex-item就会在.flex-container的垂直方向上居中显示,布局瞬间变得美观又整齐。
BFC 和 FFC,到底该怎么选?
BFC 和 FFC 都是前端布局的利器,但它们的应用场景不太一样 。BFC 更像是一个 “传统守护者”,主要用于解决一些传统布局中遇到的问题,比如清除浮动、防止外边距重叠、实现两栏布局等 。而 FFC 则是 “潮流新贵”,特别适合构建各种灵活、响应式的布局结构,像导航栏、卡片布局、产品展示区等 。
比如说做一个响应式的导航栏,左边是 logo,右边是几个导航链接,用 FFC 就能轻松实现两边对齐,而且在不同屏幕尺寸下都能保持良好的布局效果:
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
height: 60px;
background-color: #333;
}
.logo {
color: white;
font-size: 20px;
}
.nav-links a {
color: white;
margin-left: 15px;
text-decoration: none;
}
<div class="nav">
<div class="logo">Logo</div>
<div class="nav-links">
<a href="#">首页</a>
<a href="#">产品</a>
<a href="#">关于我们</a>
</div>
</div>
这里的.nav作为 FFC 容器,justify-content: space-between让 logo 在左边,.nav-links在右边,align-items: center又让它们在垂直方向上居中,整个导航栏看起来简洁又大气。
再比如做一个产品展示区,每个产品卡片需要根据屏幕大小自动调整排列方式,这时候 FFC 的flex-wrap属性就能大显身手,让卡片在不同屏幕尺寸下都能合理布局,不会出现拥挤或者空白过多的情况。
而如果是在一些需要兼容旧浏览器,或者处理一些复杂的嵌套布局,防止内部元素影响外部布局的场景下,BFC 就会发挥重要作用。比如在一个复杂的表单布局中,使用 BFC 来隔离各个表单元素组,确保它们的外边距不会相互干扰,布局稳定。
总之,BFC 和 FFC 就像是我们前端布局工具箱里的两件得力工具 。作为新手,掌握好它们的特性和应用场景,在以后的项目中就能根据不同的需求,灵活选择,打造出漂亮又实用的页面布局啦!
希望这篇文章能帮助大家对 BFC 和 FFC 有更深入的理解,一起在前端的学习道路上越走越顺!