深入理解BFC:解决margin折叠和浮动高度塌陷的利器
目录
1、什么是BFC
2、边距折叠与BFC的关系
2.1 父子折叠
2.2 兄弟折叠
2.3 空元素折叠
3、BFC作用详解
4、如何触发BFC
5、总结
1、什么是BFC
- BFC(Block Formatting Context,块级格式化上下文)是W3C CSS视觉格式化模型中的一个概念。
- 它是一个独立的渲染区域,内部元素的布局不会影响外部元素,外部元素也不会影响它内部的布局。
- 在BFC中,块盒子会按照一定规则进行布局,形成一个独立的容器。
- 普通的块级盒子默认不创建BFC,只有满足一定条件才会触发BFC,盒子才会拥有BFC。
2、边距折叠与BFC的关系
边距折叠:在CSS中,垂直方向相邻的两个外边距有时会合并成一个外边距(为较大值的外边距),表现为margin叠加不生效。
常见的折叠情况包括:父子折叠、兄弟折叠、空元素折叠。
2.1 父子折叠
描述:父元素的上下外边距会和第一个子元素的上外边距或最后一个子元素的下外边距发生折叠,前提是父元素本身没有边框、内边距、行内内容且没有触发BFC。
代码示例:从下面的代码我们可以看出,给father盒子设置高度自适应,father的上边距是50px,下边距是100px,但是father的第一个子元素的上边距是20px,最后一个子元素的下边距是200px,此时整个father盒子的上边距是最大的也就是父盒子的50px,下边距也是最大也就是子盒子的200px。
解决办法:父盒子触发BFC
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.father {margin-top: 50px;width: 300px;background-color: #a2f565;margin-bottom: 100px;}.father-1 {width: 300px;height: 300px;background-color: #659ff5;}.child-1 {width: 200px;height: 100px;background-color: aqua;margin-top: 20px;}.child-2 {width: 200px;height: 100px;background-color: cornflowerblue;margin-bottom: 200px;}</style>
</head>
<body>
<div class="father"><div class="child-1"></div><div class="child-2"></div>
</div>
<div class="father-1"></div>
</body>
</html>
2.2 兄弟折叠
描述:相邻的兄弟块级元素上下外边距会合并成一个较大的 margin,而不是相加。
代码示例:如下面代码所述,子元素1的下边距是100px,子元素2的上边距是200px,此时他们会合并margin,取最大值也就是200px。
解决办法:在折叠的兄弟之间加一个元素用来阻断折叠
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.father {width: 300px;background-color: #a2f565;}.child-1 {width: 200px;height: 100px;background-color: aqua;margin-bottom: 100px;}.child-2 {width: 200px;height: 100px;background-color: cornflowerblue;margin-top: 200px;}</style>
</head>
<body>
<div class="father"><div class="child-1"></div><div class="child-2"></div>
</div>
</body>
</html>
2.3 空元素折叠
描述:没有内容、边框、内边距且高度为0的元素上下margin合并。
代码示例:empty没有设置高度,但是他的margin与他相邻的两个盒子折叠了。与兄弟折叠类似,也就是其中一个兄弟盒子没有高度只有margin。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><title>空元素折叠示例</title><style>.box {width: 200px;background-color: lightblue;margin: 20px 0;}.empty {height: 0;margin: 30px 0;background-color: pink; /* 方便观察 */}</style>
</head>
<body><div class="box">上方盒子</div><div class="empty"></div> <!-- 空元素,height: 0,margin: 30px 0 --><div class="box">下方盒子</div></body>
</html>
3、BFC作用详解
BFC的作用之一就是阻止这些折叠现象。 当元素创建了BFC后,内部元素的margin不会与外部元素的margin折叠,从而避免布局异常。
1. 阻止外边距折叠
描述:BFC使其内部和外部的垂直margin不会发生折叠,解决了margin叠加导致的间距问题。
2.包含浮动元素
描述:浮动元素会脱离文档流,导致父元素高度塌陷。BFC容器会包裹浮动子元素,使父元素高度自适应。
3.防止元素重叠
描述:BFC中的元素不会与外部浮动元素重叠,保证布局的整洁。
4.清除浮动
描述:通过触发BFC,可以避免父元素高度塌陷,从而实现清除浮动效果。
4、如何触发BFC
overflow 属性非 visible | overflow: hidden; | 设置为 hidden 、auto 、scroll 等均可触发 BFC |
display: flow-root | display: flow-root; | 新增的 CSS 属性,专门用于创建 BFC |
浮动元素 | float: left; 或 float: right; | 浮动元素自动形成 BFC |
绝对定位或固定定位元素 | position: absolute; 或 position: fixed; | 绝对定位元素形成 BFC |
弹性盒子布局 | display: flex; 或 display: inline-flex; | Flexbox 容器形成 BFC |
网格布局 | display: grid; 或 display: inline-grid; | Grid 容器形成 BFC |
5、总结
推荐使用flex布局,对于大多数的BFC方法在实际测试中并不能有效解决盒子折叠问题,与其纠结各种坍塌堆叠问题,不如使用flex布局,解决你的所有烦恼。SO不要再研究BFC了,没有什么实际作用,所有的解决办法也不能解决你的问题。
理由1:解决父子堆叠问题
让父盒子触发BFC的确能解决第一个或者是最后一个子盒子带来的堆叠问题,但是!!!用flex布局也能够解决。这是不推荐研究理由之一。
理由2:解决兄弟盒子堆叠问题
在实际测试中,发现对于overflow、display:flow-root、position:relation/absoulate这些触发BFC方法都不能都解决兄弟盒子堆叠问题!!!在不使用弹性布局等其他方法的情况下能够解决的方式有给两个兄弟盒子之间插入一个新的盒子用来阻断堆叠问题,但是这种方法和BFC有一毛钱关系吗???很显然没有吧!!!
在这里,我又又又可以使用flex布局来解决这个问题,可以高效的解决兄弟盒子堆叠的问题。
理由3:对于包含浮动元素、解决父盒子坍塌、阻止外边距折叠等等的其他问题,基本上都能使用flex布局解决(虽然说flex也算是触发BFC的方式之一),但是为什么有的问题有的触发方法却不能解决问题呢???
总结:对于本篇文章,相当于只是介绍了一下BFC,只要知道BFC是块级格式化上下文就行了,理论上来说BFC能够解决的问题有:阻止外边距折叠、包含浮动元素、清除浮动、防止元素重叠,实际上来说有些触发BFC的方式并不能解决实际问题,但是flex布局能够解决大部分问题。然后记住触发BFC的方式:overflow:hidden/auto/scoll、position:relative/absolute、display:flow-root/flex/grid/inline-block、float:left/right。