本系列面试题旨在学会相关知识点,从而轻松应对面试题的各种形式,本文讲解了 BFC
以及 利用 BFC
解决外边距重叠问题。
块级格式化上下文(BFC)
BFC( Block Formatting Context
)
什么是 BFC
BFC
是一个独立的区域,它内部的元素都依照它的规则渲染,并且不会与 BFC
外部打交道。
BFC 的布局规则
- 内部的盒子会在垂直方向,一个个地放置;
- 盒子垂直方向的距离由
margin
决定,属于同一个BFC
的两个相邻盒子的上下margin
会发生重叠; - 每一个元素的左边,与包含块的左边相接触(对于从右往左的布局,则相反),即使存在浮动也是如此;
BFC
的区域不会与float
重叠;BFC
就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此;- 计算
BFC
的高度时,浮动元素也參与计算。 - 当一个元素设置了新的
BFC
后,就和这个元素外部的BFC
没有关系了,这个元素只会去约束自己内部的子元素。
以下方式会创建 BFC
- overflow:不为
visible
; - float: 不为
none
; - display: 为
inline-block
、table
、table-cell
、table-caption
、flex
、inline-flex
、grid
、inline-grid
、flow-root
; - position: 为
absolute
或者fixed
;
可以简单的理解成 OFDP
,当面试官问到你的时候,你回答个 OFDP
,面试官大概率就知道你理解这个知识点了。
父子元素边距重叠
场景一:先来看这段代码,预计实现的结果应该是父容器距离页面顶部 100px
,子容器距离父容器 100px
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
margin-top: 100px;
}
.content {
width: 200px;
height: 200px;
background: green;
margin-top: 100px;
}
</style>
<body>
<div class="container">
<div class="content"></div>
</div>
</body>
但是我们却得到了这样的结果,父容器距离页面上方 100px
,但是子容器和父容器之间却没有距离。
场景二:再来看这段代码,预计实现的结果应该是父容器紧贴页面顶部,子容器距离父容器 100px
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
}
.content {
width: 200px;
height: 200px;
background: green;
margin-top: 100px;
}
</style>
<body>
<div class="container">
<div class="content"></div>
</div>
</body>
结果还是一样的,子容器和父容器之间没有距离,父容器却和页面顶部产生了距离,这是怎么回事呢?
现象: 发生了边距重叠,一个盒子和其子孙的边距重叠。
规则:正正取最大,负负取最负,正负就相加。
原因:根据规范,一个盒子如果没有添加 BFC
,那么它的上边距应该和其文档流中的第一个子元素的上边距重叠。
解决: 通过给父容器添加 overflow: hidden
属性,使之成为 BFC
。
.container {
overflow: hidden;
}
这回就是我们想要的结果了。
原理:BFC
在页面上是一个独立的容器,父子/外部/内部互不影响。
兄弟元素边距合并
场景三:再来看这段代码,两个兄弟元素,一个下边距是 100px
,另一个上边距 100px
,预计的结果是两个兄弟元素之间的距离是 200px
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
}
.box1 {
width: 200px;
height: 200px;
background: green;
margin-bottom: 100px;
}
.box2 {
width: 200px;
height: 200px;
background: blue;
margin-top: 100px;
}
</style>
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
但是两个兄弟元素之间的距离只有 100px
。
现象:发生了边距重叠,两个兄弟元素的上边距和下边距发生了重叠。
规则:正正取最大,负负取最负,正负就相加。
原因:块级元素的上外边距或下外边距有时(直接接触/相邻时)会合并为一个外边距。
解决:通过给其中一个兄弟元素添加父容器并添加 overflow: hidden
属性,使之成为 BFC
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
}
.father {
overflow: hidden;
}
.box1 {
width: 200px;
height: 200px;
background: green;
margin-bottom: 100px;
}
.box2 {
width: 200px;
height: 200px;
background: blue;
margin-top: 100px;
}
</style>
<body>
<div class="container">
<div class="father">
<div class="box1"></div>
</div>
<div class="box2"></div>
</div>
</body>
这回就是我们想要的结果了。
原理:属于不同 BFC
的元素垂直方向边距不会发生重叠。
空元素边距合并
场景四:两个兄弟元素之间有四个空元素,每个空元素有 25px
的 margin-top
,预计的结果是两个兄弟元素之间的距离是 100px
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
}
.box1 {
width: 200px;
height: 200px;
background: green;
}
.box2 {
width: 200px;
height: 200px;
background: blue;
}
.null {
margin-top: 25px;
}
</style>
<body>
<div class="container">
<div class="box1"></div>
<p class="null"></p>
<p class="null"></p>
<p class="null"></p>
<p class="null"></p>
<div class="box2"></div>
</div>
</body>
但是结果却是只有一个空元素的距离,也就是 25px
。
现象:发生了边距重叠,所有的空元素的边距重叠成一个空元素的边距。
原因:如果一个块级元素没有任何内容并且设置了 margin-top
和 margin-bottom
时会发生 margin
合并。
解决:给每一个添加父容器并添加 overflow: hidden
属性,使之成为 BFC
。
<style>
body {
background: gray;
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 600px;
background: yellow;
}
.box1 {
width: 200px;
height: 200px;
background: green;
}
.box2 {
width: 200px;
height: 200px;
background: blue;
}
.null {
margin-top: 25px;
}
.father {
overflow: hidden;
}
</style>
<body>
<div class="container">
<div class="box1"></div>
<div class="father">
<p class="null"></p>
</div>
<div class="father">
<p class="null"></p>
</div>
<div class="father">
<p class="null"></p>
</div>
<div class="father">
<p class="null"></p>
</div>
<div class="box2"></div>
</div>
</body>
这样就达到了我们的目的。但是这种情况实际应用场景几乎没有,了解一下就行。
原理:属于不同 BFC
的元素垂直方向边距不会发生重叠。
感觉有帮助的小伙伴请点赞