BFC
块格式化上下文(Block Formatting Context,BFC) 是 web 页面的可视化 CSS 渲染的一部分, 是块盒子的布局过程发生的区域, 也是浮动元素与其他元素交互的区域.
下列方式会创建块格式化上下文:
根元素(<html>)
浮动元素(元素的 float 不是 none)
绝对定位元素(元素的 position 为 absolute 或 fixed)
行内块元素(元素的 display 为 inline-block)
表格单元格(元素的 display 为 table-cell)
表格标题(元素的 display 为 table-caption)
匿名表格单元格元素(元素的 display 为 table,inline-table)
display 值为 flow-root 的元素(兼容性不好)
弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
元素(display 为 grid 或 inline-grid 元素的直接子元素)
overflow 值不为 visible 的块元素
上述创建 BFC 的 CSS 列为以下几类:
HTML 根元素
- float(不为 none 即可)
- left
- right
- position
- absolute
- fixed
- display
- inline-block
- flex,inline-flex
- grid,inline-grid
- table,table-cell,table-caption
- flow-root
块格式化上下文对浮动定位 (参见 float) 与清除浮动 (参见 clear) 都很重要.
总结:
浮动定位和清除浮动时只会应用于同一个 BFC 内的元素, 浮动不会影响其它 BFC 中元素的布局;
而清除浮动只能清除同一 BFC 中在它前面的元素的浮动;
外边距折叠 (Margin collapsing) 也只会发生在属于同一 BFC 的块级元素之间;
BFC 就是页面上的一个隔离的独立容器, 容器里面的子元素不会影响到外面的元素, 反之亦然;
计算 BFC 的高度时, 考虑 BFC 所包含的所有元素, 连浮动元素也参与计算;
浮动盒区域不叠加到 BFC 上;
高度坍塌和清除浮动
高度坍塌是指父元素本来应该包括子元素的高度, 但是实际上父元素比子元素的高度要小.
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <style>
- .container { margin-left: 50px; background: red; } .box1 { float: left;
- width: 200px; height: 200px; background-color: blue; } .box2 { width: 400px;
- height: 100px; background: cyan; }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="box1">
- </div>
- <div class="box2">
- </div>
- </div>
- </body>
- </HTML>
1,box1 浮动之后, 父元素的高度就坍塌了, 解决办法是让父元素触发 BFC , 这样 BFC 内的元素就无法影响到外面了, 给 container 加上 overflow: auto; 即可. 加上之后变成这样了.
2, 也可以通过给 container 添加 ::after 伪元素, 清除左右浮动来防止坍塌.
- .container::after {
- content: "";
- display: block; /* 不能少 */
- clear: left;
- }
3, 还可以通过在父元素的最后添加一个块级元素并清除浮动.
- <div class="container">
- <div class="box1"></div>
- <div class="box2"></div>
- <div style="clear: both;"></div>
- </div>
4, 图中有另外一个问题是 box2 被 box1 盖住了一部分, 这是因为 box1 浮动起来了, 显然只需要清除浮动即可. 使用 BFC 清除, 对应的规则是 浮动盒区域不叠加到 BFC 上, 给 box2 添加 overflow: auto; 之后显示正常.
5, 同样我们也可以通过 clear:both; 来清除浮动, 只需要给 box2 添加 clear: both;, 但是效果和 BFC 清除有点不一样, 因为 clear: both; 表示元素下移清除左右浮动.
外边距折叠
块级元素的上外边距和下外边距有时会合并 (或折叠) 为一个外边距, 其大小取其中的最大者, 这种行为称为外边距折叠(margin collapsing), 有时也翻译为外边距合并. 注意浮动元素和绝对定位元素的外边距不会折叠.
外边距折叠的基本情况:
相邻元素之间 毗邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动).
父元素与其第一个或最后一个子元素之间 如果在父元素与其第一个子元素之间不存在边框, 内边距, 行内内容, 也没有创建块格式化上下文, 或者清除浮动将两者的 margin-top 分开; 或者在父元素与其最后一个子元素之间不存在边框, 内边距, 行内内容, height,min-height,max-height 将两者的 margin-bottom 分开, 那么这两对外边距之间会产生折叠. 此时子元素的外边距会 "溢出" 到父元素的外面.
从上面一段话总结下可以去除外边距折叠的方法:
父元素添加边框(border);
父元素添加内边距(padding);
父子元素之间存在行内元素 <span> 匿名元素;
父子元素之间存在触发 BFC 的元素(插入一个 display: flex 的块级元素);
父元素触发 BFC(overflow: auto; 等);
外边距折叠的一些规则:
即使某一外边距为 0, 这些规则仍然适用. 因此就算父元素的外边距是 0, 第一个或最后一个子元素的外边距仍然会 "溢出" 到父元素的外面.
如果参与折叠的外边距中包含负值, 折叠后的外边距的值为最大的正边距与最小的负边距 (即绝对值最大的负边距) 的和.
如果所有参与折叠的外边距都为负, 折叠后的外边距的值为最小的负边距的值. 这一规则适用于相邻元素和嵌套元素.
以下面代码为例:
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0"
- />
- <meta http-equiv="X-UA-Compatible" content="ie=edge" />
- <title>
- Document
- </title>
- <style>
- .container { background-color: deeppink; } .child { } div { background-color:
- cyan; } body { margin: 0; background-color: yellow; }
- </style>
- </head>
- <body>
- <div class="container" style="margin-top: 10px;">
- <div class="child" style="margin-top: 50px;">
- Word
- </div>
- </div>
- </body>
- </HTML>
由于外边距折叠且外边距都为正, 所以取大的 50px
1, 给 container 添加 border, 成功去除折叠.
- .container {
- background-color: deeppink;
- border: 1px solid #000000;
- }
2, 给父元素增加 padding, 正常了.
- .container {
- background-color: deeppink;
- padding: 1px;
- }
3, 给父子元素之间添加内联或者匿名元素, 添加一个 , 去除折叠了, 但是新增的元素会占据额外的空间, 所以不推荐.
- <div class="container" style="margin-top: 10px;">
- <div class="child" style="margin-top: 50px;">Word</div>
- </div>
4, 父子元素之间添加触发了 BFC 的元素, 正常了.
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
- <div class="container" style="margin-top: 10px;">
- <div style="display: flex;"></div>
- <div class="child" style="margin-top: 50px;">Word</div>
- </div>
5, 父元素触发 BFC, 正常了.
- .container {
- background-color: deeppink;
- overflow: auto;
- }
来源: http://www.jianshu.com/p/1440829f5cca