一、BFC
1、定义:
先给一个官方的定义:(可能会看不懂我也不懂)
Formatting context(格式化上下文)是W3CCSS2.1规范中的一个概念。每个渲染区域用formattingContext表示,它是页面中的一块渲染区域,并且有一套渲染规则。它决定了其子元素将如何定位,以及和其他元素的关系和相互作用
再看下面这个定义:(一点点懂)
BFC(Block FormattingContext),块级格式化上下文。相当于制定一种如BFC这样的规则,在普通流中按照该规则进行布局。
在正常流中的盒子要么属于块级格式化上下文(BFC),要么属于内联格式化上下文,即块级元素在页面渲染的时候遵循怎么样的规则,它们之间有怎么样的作用。
再看这个:(还是一点点懂)
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且BFC具有普通容器所没有的一些特性。通俗一点来讲,可以把 BFC理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
总结:BFC没有定义,只有功能或特性
2、BFC会在哪里产生(官方的)
只要元素满足下面任一条件即可触发 BFC 特性
(1)body根元素
html里的根元素产生相应的“块级格式化上下文”这类的规则,如某些规则:块级容器可以充满父容器,父容器可以被子元素撑开,外边距产生合并,渲染顺序是从上到下(同一个块级格式化上下文中相邻块级盒之间的竖直margin会合并)
(2)浮动元素:float除了none
以外的值;
如float:left;
该元素属性本身也产生了相应的块级格式化上下文。该元素产生的BFC与所在的根元素的BFC互不影响,此元素的作用域,则为该元素服务,与根元素产生一个隐形的边界
(3)绝对定位元素:position
为absolute
或fixed
;
(4)display
为inline-block
(非块盒的块容器), flex
, 或inline-flex
;
(5)overflow
除了visible
以外的值(hidden
、auto
、scroll
)
3、应用
这里的例子截取自该文章:10 分钟理解 BFC 原理
(1)功能1
让两个相邻的元素界限分明(同一个 BFC 下外边距会发生重叠或合并)
代码如下:1
2
3
4
5
6
7
8
9
10
11<head>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
</head>
<div></div>
<div></div>
从效果上看,因为两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div的下边距和第二个div的上边距发生了重叠,所以两个盒子之间距离只有100px,而不是 200px。
如图:
首先这不是 CSS 的bug,我们可以理解为一种规范。如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 <div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
<style>
.container {
overflow: hidden; ✔️
}
p {
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
</style>
这时候,两个盒子边距就变成了 200px ,
如图:
(2)功能2
子元素被父元素包裹起来(BFC可以包含浮动的元素)(可代替clearfix
来清除浮动)
display:flow-root;
让当前元素触发BFC(正交,考虑浏览器兼容)overflow:hidden;
将溢出隐藏浮动的元素会脱离普通文档流,
来看下下面一个例子,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<style>
.father{
border: 1px solid #000;
}
.son{
width: 100px;
height: 100px;
background: #eee;
float: left;
}
</style>
<div class=father>
<div class=son></div>
</div>
由于父元素(father)内子元素(son)进行浮动,脱离了“父亲”的文档流,所以容器只剩下 2px 的边距高度。此时可以触发容器的 BFC,那么“father”就可以包裹住“son”出去的浮动元素。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<style>
.father{
border: 1px solid #000;
overflow:hidden; ✔️
}
.son{
width: 100px;
height: 100px;
background: #eee;
float: left; ✔️
}
</style>
<div class=father>
<div class=son></div>
</div>
(3)功能3
BFC 可以阻止元素被浮动元素覆盖。先来看一个文字环绕效果,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<style>
.box1{
height: 100px;
width: 100px;
float: left;
background: lightblue;
}
.box2{
width: 200px;
height: 200px;
background: #eee;
}
</style>
<div class=box1>我是一个左浮动的元素</div>
<div class=box2>我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;</div>
此时,浮动元素浮在第二个元素上,第二个元素有部分区域被浮动元素所覆盖(但文本信息不会被浮动元素所覆盖) 。如果想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入overflow:hidden;
或者display:flow-root;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<style>
.box1{
height: 100px;
width: 100px;
float: left; ✔️
background: lightblue;
}
.box2{
width: 200px;
height: 200px;
background: #eee;
overflow:hidden; ✔️
/*或 display: flow-root; */ ✔️
}
</style>
<div class=box1>
我是一个左浮动的元素
</div>
<div class=box2>
我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;
</div>
就会变成:BFC 浮动处理
用来实现两列自适应布局:即左边宽度固定,如果想右边的内容自适应宽度,可以去掉上面右边内容的宽度(如果右边定宽,窄页面时,则会自动换到下一行排列)
二、边距合并
1、讲例子
案例1:
当实际中希望#header
和h1
之间产生一点缝隙(或间距),即使将h1设置 margin:50px;
,作为块级元素的h1
,margin
左右生效,而上下则是#header+h1
整体向下移动50px
这便是,外边距合并
案例2:
看案例似乎是<h1>
和<p>
标签所设置的外边距各30px,两者之间的间距理论来讲应该是60px,但事实上这是两个相邻元素的外边距产生合并,下边距<margiin-bottom>
和上边距<margin-top>
合并之后取较大值,这里为30px
这也是,外边距合并
2、合并场景
(1)相邻元素合并
同案例2
(2)父子合并h1
和header
,或者再嵌套元素或者与其的祖先元素嵌套,均能产生外边距合并,这些都能称之为“父子合并” ,如图:
(3)自己合并
如图,块级元素合并,无默认样式即靠在一起;含有p标签(含内容)的块级元素,则有默认上下margin
,所以detail
和footer
则会产生缝隙(或间距)
.footer
元素为空内容,设置 margin:30px;
,即说明上边距和下边距合并后的外边距总值是60px,不过.footer
元素为空内容,所以页面效果仍然呈现30px,说明css元素中外边距合并的另一种情况:
自己和自己合并: 如图:
三、取消合并(如何去解决外边距合并?)
1、边框、padding
存在于父子合并
为何#header
和h1
能够产生合并?即#header
没有border
和padding
(即一个可与外界隔离的边界线),导致h1
自带的一个margin
,冲出该边界,与#header
合并
尝试在#header
里添加边框(图1)或者加padding
(内边距)(图2),让#header
和h1
的margin-top
,内外分开,即能做到不让外边距合并,如图:
2、BFC
如何让一个元素生成bfc?bfc可认为是拥有一片独立的空间,和其他的空间(或其他的文档流)区别开。注:添加bfc元素属性,可以取消合并有可能产生副作用
(1)父子元素不产生合并
A、添加:overflow:hidden;
B、添加 :float:left;
C、添加: display:inline-block;
D、添加: position:absolute;
(2)相邻元素不产生合并
A、添加:浮动元素
B、添加:overflow:hidden;
生成BFC,相当于生成了一个边界,即边框作为一个边界,有了边界之后,#header+h1
父子元素便不能冲破该边界,自然与#detail
元素的不产生合并.
【重点】: 而相邻元素之间的margin
,可以认为不是该父子元素边界内,同样会产生合并。通常处理相邻元素之间的间距合并问题(除浮动外,浮动时不会被合并),即不考虑合并问题,直接设置为:margin-top:___px;