BFC
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,行内元素布局所在的环境则属于IFC。
BFC:块级元素所在的布局环境就是BFC。
形成BFC的条件
- 根元素(< html >)
- 浮动元素(float 值不为 none)
- 绝对定位元素(position 值为 absolute 或 fixed)
- 行内块元素(display 值为 inline-block)
- 表格单元格(display 值为 table-cell,HTML 表格单元格默认值)
- 表格标题(display 值为 table-caption,HTML 表格标题默认值)
- 匿名表格单元格元素(display 值为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是 HTML table、tr、tbody、thead、tfoot 的默认值)或 inline-table)
- overflow 值不为 visible、clip 的块元素
- display 值为 flow-root 的元素
- contain 值为 layout、content 或 paint 的元素
- 弹性元素(display 值为 flex 或 inline-flex 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
- 网格元素(display 值为 grid 或 inline-grid 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
- 多列容器(column-count 或 column-width (en-US) 值不为 auto,包括column-count 为 1)
BFC的作用
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 may become narrower due to the floats).
上面的意思是:
在同一个BFC中,每个盒子都会在垂直方向上一个接一个排列,竖直距离由 margin 决定,相邻外边距会折叠为两个外边距中最大的一个。
每个盒子的左外边缘与包含该盒子父元素的左边缘相接触(从右往左排列的则是右外边缘与父元素的右边缘接触)。
也就是说,在一个BFC中,元素会按照BFC内定的规则去排列和摆放。
BFC解决相邻margin折叠问题
因为处于同一个BFC且有相邻的 margin则会造成折叠问题,所以只需要让其中一个处于不相同的BFC则可以解决折叠问题。
<html>
<head>
<style>
.container {
overflow: auto; // 让 class 为 container 的块级元素产生新的 BFC 环境,则处于 container 形成的 BFC 中的 box1 则和处于由 html 形成的 BFC 环境的 box2 就是两个不相同的 BFC 所以折叠现象消失。
}
.box1 {
height: 200px;
width: 400px;
background-color: orange;
margin-bottom: 30px;
}
.box2 {
height: 150px;
background-color: purple;
margin-top: 50px;
}
</style>
</head>
<body>
<div class='container'> // BFC 环境是由 html 形成的
<div class='box1'> // BFC 环境是由 container 形成的
<div>
</div>
<div calss='box2'> // BFC 环境是由 html 形成的
</div>
</body>
</html>
BFC解决float导致的高度塌陷问题
子元素 float 导致父级元素不能获取到子元素的高度,是因为子元素脱离了当前文档流,所以造成父元素的高度塌陷,而 BFC 则可以解决这个问题。但是 BFC 不能解决由定位引起的父元素高度塌陷问题!
<html>
<head>
<style>
.container {
background-color: orange;
overflow: auto; // 形成新的 BFC 来解决高度塌陷问题。前提条件是 container 高度为 auto
}
.item {
width: 400px;
height: 200px;
box-sizing: border-box;
border: 1px solid black;
float: left;
background-color: red;
}
</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>
原理: 在 BFC 的高度为 auto 的情况下,按如下方法进行计算高度:
- 如果只有 inline-level,是行高的顶部和底部的距离;
- 如果有 block-level,是由最顶层的块上边缘和最底层块盒子的下边缘之间的距离;
- 如果有绝对定位元素,将被忽略;
- 如果有浮动元素,那么会增加高度以包括这些浮动元素的下边缘。
通过清除浮动来解决高度塌陷问题
<html>
<head>
<style>
.container {
background-color: orange;
}
.item {
width: 400px;
height: 200px;
box-sizing: border-box;
border: 1px solid black;
float: left;
background-color: red;
}
.clear_fix::after {
// 清除浮动解决高度塌陷
content: '';
display: block;
clear: both;
height: 0;
visibility: hidden;
}
</style>
</head>
<body>
<div class="container clear_fix">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>