什么是BFC?聊聊BFC及其应用
什么是BFC?BFC的使用场景是什么?BFC解决高度塌陷问题。BFC解决margin重叠问题。BFC原理
什么是BFC?聊聊BFC及其应用
什么是BFC?这个在刚接触前端时候一直困扰自己的东西,知道如何用却不知道原理。
正所谓知其然,知其所以然,今天来对它做一个总结!
什么是BFC?
BFC 一直是面试躲不过的一个命题,之前也看过很多篇文章,但是讲的都相似却讲不清楚,只聊使用却不聊原理,所以一直也记不住。今天通过看其他文章并融入自己的理解作一次总结,希望有所帮助。
在此之前,我们先了解一下FC是什么:
看下W3c文档对标准流和formatting context的解释:
Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.
从中我们能得到如下信息:
- 所有盒子都属于一个FC
- 块级元素的布局属于一个BFC。例如div/p等
- 行内元素的布局属于一个IFC。例如span img等
简而言之 - 块级元素
所在的布局和上下文就是BFC(Block Formatting Context) - 行内级元素
所在的布局和上下文就是IFC(Inline Formatting Context)
怎样能创建BFC?BFC在哪里?
MDN上作了如下解释(形成BFC的条件):
除了文档的根元素 () 之外,还将在以下情况下创建一个新的 BFC:
- 使用float 使其浮动的元素
- 绝对定位的元素 (包含 position: fixed 或position: sticky
- 使用以下属性的元素 display: inline-block
- 表格单元格或使用 display: table-cell, 包括使用 display: table-* 属性的所有表格单元格
- 表格标题或使用 display: table-caption 的元素
- 块级元素的 overflow 属性不为 visible
- 元素属性为 display: flow-root 或 display: flow-root list-item
- 元素属性为 contain: layout, content, 或 strict
- flex items
- 网格布局元素
- multicol containers
- 元素属性 column-span 设置为 all
理解:html是一个BFC, 但是body不是一个BFC,overflow属性除了visible外都是一个BFC
下面我们作如下示例来加深理解:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BFC</title>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
这段代码中的box1和box2就都是在html根元素的BFC中布局的。
BFC的应用
解决margin重叠问题
margin重叠问题原因:
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the ‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.
In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself href=“https://www.w3.org/TR/CSS2/visuren.html#bfc-next-to-float”>may become narrower due to the floats).
从中我们可以了解到:
- 在BFC中,box会在垂直方向一个挨着一个进行排列,
因此块级元素会独占一行
- 垂直方向上的距离由margin决定
- 同一个BFC中,相邻的两个块之间会出现margin折叠(取两者之间较大的,可使用此特性解决margin重叠问题)
- 在BFC中,每个元素左边缘都是紧挨包含块左边缘的。
html就是一个BFC,因此每一个元素都是默认靠左对齐。
margin重叠问题解决:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BFC</title>
<style>
.box1 {
height: 200px;
width: 400px;
background-color: red;
margin-bottom: 30px;
}
.box2 {
height: 150px;
width: 400px;
background-color: burlywood;
margin-top: 50px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
此时box1和box2同事处于html的BFC中,所以会出现margin重叠的情况,取50px;
所以我们如果让它们不在同一个BFC中,就可以解决这个问题:
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BFC</title>
<style>
.box1 {
height: 200px;
width: 400px;
background-color: red;
margin-bottom: 30px;
}
.box2 {
height: 150px;
width: 400px;
background-color: burlywood;
margin-top: 50px;
}
.top{
overflow: hidden;
}
</style>
</head>
<body>
<div class="top">
<div class="box1"></div>
</div>
<div class="box2"></div>
</body>
</html>
这样我们给box1加一层父元素,并加属性overflow:hidden
让box1处于新的BFC下,就可以让box1和box2处于不同的BFC,也就解决了margin重叠的问题。
解决高度塌陷的问题
当dom设置float浮动后,浮动元素会脱离文档流,导致父元素高度塌陷。见下面例子:
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport content="width=device-width, initial-scale=1.0" />
<title>BFC</title>
<style>
.container {
background-color: orange;
padding:10px;
}
.item {
width: 400px;
height: 200px;
box-sizing: border-box;
border: 1px solid #000;
float: left;
background-color: #f00;
}
</style>
</head>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
为了可以看清父元素(橙色),我加了10px的padding值,我们可以看到设置了float的item并没有撑起父元素container的高度(此时container高度为0
)。
此时想解决高度塌陷问题需要满足两个条件:
- 浮动元素的父元素触发BFC,形成独立的块级格式化上下文。
- 浮动元素的父元素高度为auto。
因此我们给.container加上“overflow:hidden”即可。(不绝对,只要让父元素触发BFC即可
)
当BFC高度是auto时,高度是这样计算的:
- 如果只有inline-level,是行高的顶部和底部的距离
- 如果有block-level,是有最底层的块上边缘和最底层块盒子的下边缘之间的距离(有margin也会计算在内)
- 如果有绝对定位元素,将被忽略(所有我们无法通过BFC解决绝对定位的高度塌陷问题)
- 如果有浮动元素,那么会增加高度以包括这些浮动元素的下边缘(这才是BFC能解决浮动元素塌陷问题的原因,并不是因为浮动元素向上汇报了高度)
以上就是今日的分享!希望对大家理解BFC有所帮助。
更多推荐
所有评论(0)