接触写博客有一段时间了,都是边学边学着写,但总感觉写的凌乱,想起啥写啥。这几天在刷红宝书,收获还是蛮多的,决定结合自己的学习,写一个系列,我叫它 「前端料包」,旨在巩固前端基础,努力提升自己,同时也乐于做一个分享者。这个系列包括但不限于下面脑图中的内容,目录和发文顺序暂且如下图,今天带来的是第二篇。
在讲BFC之前,先说一下文档流。我们常见的文档流有三种:浮动流、定位流和普通流,而BFC中的FC就是其中的普通流。
FC(Formatting context)
Formatting context
是 W3C CSS2.1
规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context
有 Block fomatting context
(简称BFC)和 Inline formatting context
(简称IFC)。此外还有CSS3中新增的GFC(grid formatting context
)和FFC(flex formatting context
),此处不做展开。
BFC 定义
BFC(Block formatting context)
直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box
参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
Box
Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:
block-level box:
display 属性为 block, list-item, table 的元素,会生成block-level box。并且参与 block fomatting context;
inline-level box
:display属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与
inline formatting context;
run-in box:
css3 中才有。
margin box
的左边, 与包含块border box
的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。满足下列条件之一就可触发BFC
float
除 none
以外的值;position (absolute、fixed)
;display
为 inline-block, table-cell, table-caption, flex, inline-flex
;overflow
除了 visible
以外的值 (hidden、auto、scroll
)。(1)解决margin重叠问题
由于浏览器解析页面是由上而下的,上下外边距会取最大值,就是所谓的边距重叠问题(对应上面提到的特性2),于是出现如下的布局问题
<head>
<meta charset="UTF-8">
<title>BFCtitle>
<style>
.d1 {
width: 200px;
height: 200px;
background-color: chartreuse;
margin-bottom: 20px;
}
.d2 {
width: 200px;
height: 200px;
background-color: red;
margin-top: 30px;
}
style>
head>
<body>
<div class="d1">div>
<div class="d2">div>
body>
我们在网页设计时如果想要垂直方向上的外边距不重叠,可以通过给其中一个元素加一个父元素,并触发父元素的BFC,这样两个div就不属于同一个BFC,垂直方向上的外边距就不会重叠,看代码:
<head>
<meta charset="UTF-8">
<title>BFCtitle>
<style>
.d1 {
width: 200px;
height: 200px;
background-color: chartreuse;
margin-bottom: 20px;
}
.d2 {
width: 200px;
height: 200px;
background-color: red;
margin-top: 30px;
}
.parent{
overflow: hidden; // 触发BFC
}
style>
head>
<body>
<div class="parent">
<div class="d1">div>
div>
<div class="d2">div>
body>
<head>
<meta charset="UTF-8">
<title>title>
<style>
.left{
width: 100px;
height: 150px;
float:left;
background: greenyellow;
}
.right{
height: 200px;
background: palevioletred;
}
style>
head>
<body>
<div class="left">div>
<div class="right">div>
body>
从效果图可以看出,由于.left
设置了浮动,产生了浮动流(产生了浮动流的元素不能被块级元素看到,只能被设置了inline、文本元素看到),两个元素叠在了一起,但这并不是我们想要的结果,可通过上面提到的BFC特性之3,触发.right
的BFC来解决这个问题。
.right{
height: 200px;
background: palevioletred;
overflow: hidden;/*触发BFC*/
}
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
#clearFloat{
background: green;
border: 2px solid blue;
}
#clearFloat .box{
margin: 5px;
float: left;
width: 100px;
height: 100px;
background: red;
}
style>
head>
<body>
<div id="clearFloat">
<div class="box">sun1div>
<div class="box">sun2div>
div>
从图中可以看到,在父元素没有设置height
,子元素又float
的情况下,父元素不会被子元素撑开。这是因为设置了float
的元素脱离了文档流,飘了起来,不在原来的父元素里了(被掏空了,自然就瘪了)。同样我们可以利用上文提到的BFC特性之5,触发父元素的BFC就可以解决这个问题。
#clearFloat{
background: green;
border: 2px solid blue;
overflow: hidden;/*触发BFC,清除浮动 即使父元素不设宽高,也能被撑开*/
}
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
.p-box {
width: 300px;
height: 300px;
background-color: green;
}
.s-box {
width: 100px;
height: 100px;
background-color: cornflowerblue;
margin: 20px;
}
style>
head>
<body>
<div class="p-box">
<div class="s-box">div>
div>
body>
样式中给s-box设置了margin:20px,
但发现上边距没有出来,这时也可以通过触发父元素的BFC来解决。
以上我自己对BFC一点总结,BFC的概念比较抽象,但通过实例分析还是很好理解的,其实上面提到的很多规则我们平时布局中就经常用到,只是没有总结出来。另外,小生乃前端小白一枚,写文章只是为了让自己对该知识点有更深刻的印象和理解,写的东西也很小白,文中如有不对,欢迎指正~ 然后就是希望看完的朋友点个喜欢,也可以关注一波~ 我会持续输出!
个人博客链接
CSDN个人主页
掘金个人主页
简书个人主页
10 分钟理解 BFC 原理
BFC 神奇背后的原理
史上最全面、最透彻的BFC原理剖析