BFC+浮动+垂直方向外边距合并
一、什么是BFC
BFC全称叫做(Block Formatting Context)中文叫块级格式化上下文
MDN格式化上下文
BFC就是页面中各个元素布局的一种规则。决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
MDN上对BFC的用途,功能介绍有点多,我节选了部分,并参考网上其他资料,总结出经常遇到的BFC规则。在我的感受中,BFC完全可以和display、position、float并称为前端布局基石的一项概念,总结以为备忘。
二、BFC规则
- 内部的Box会在垂直方向,一个接一个地放置。
- 这里的BOX除了指块级盒子外,还有行框盒子,即由内联元素组成的盒子,每一行组成一个行框盒子
- 行框盒子概念见张鑫旭著《CSS世界》
- 垂直方向上的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。
- 垂直方向上外边距合并
- 每个元素的左外边缘(margin-left)与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。除非这个元素自己形成了一个新的BFC。
- BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界。因为absolute生成了BFC
- 浮动本身就是一个设置BFC的方式,但是它的父元素设置成BFC的话,浮动元素也无法超脱。
- BFC的区域不会与float box重叠。—— 解释
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
- 这也是解决父元素高度塌陷的方法
辅助记忆:BFC内部盒子的垂直排列、水平排列、自成一体、浮动(不会重叠、高度计算)
三、BFC的创建
- 浮动元素:float 除 none 以外的值。
- 绝对定位元素:position (absolute、fixed)。
- display 为 inline-block、table-cells、flex。
- overflow 除了 visible 以外的值 (hidden、auto、scroll)。
…这些比较常用。
与IE中设置haslayout涉及到的属性差不多,只是值有些不同
四、BFC的应用
4.1 清除浮动
清除浮动主要是利用了以下两点BFC规则
- 每个元素的左外边缘(margin-left)与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。
- BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界
- 计算BFC的高度时,浮动元素也参与计算
4.1.1 问题展示
高度塌陷-代码:
高度塌陷-效果:
创建BFC即可解决高度塌陷问题
4.1.2 overflow:hidden/auto/scroll
为父元素添加属性:overflow:hidden
效果:
4.1.3 display:flex
效果
4.1.4 总结
我在这里只列了两种解决父元素高度塌陷的方法。其他的方法同样可以解决这个问题,可是也会产生新的问题。
- 浮动元素:float 除 none 以外的值。
- 父元素的浮动会影响外部的布局
- 绝对定位元素:position (absolute、fixed)。
- 同样,脱离文档流也会影响其与元素的布局
- display 为 inline-block、table-cells、flex。
- overflow 除了 visible 以外的值 (hidden、auto、scroll)。
并且,无论是设置float
还是position
,又或是display:inline/table-cells
。都会使父元素具有包裹性,也可能会影响文档流中其他元素的布局
设置为display:inblock;这就影响了后面红色元素的位置。
4.2 垂直方向外边距合并
可以参考我的另一篇关于垂直方向上外边距合并的blog:外边距合并
4.2.1 问题展示
CSS样式:
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
HTML结构:
<p>Haha</p>
<p>Hehe</p>
垂直方向上外边距发生了重合
4.2.2 解决
解决外边距重叠主要原理为BFC规则第二条:
垂直方向上的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。
只要将两个元素放在不同的BFC中,他们的margin就不会重叠。所以只要使用一个BFC盒子将其中一个元素包裹起来即可,这样他们就不处于同一个BFC中了
效果:
代码:
CSS样式:
.wrap {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
HTML结构:
<p>Haha</p>
<div class="wrap">
<p>Hehe</p>
</div>