CSS 块格式化上下文 BFC

块级框参与的格式化上下文,称作块格式化上下文(Block Formatting Contexts,简称BFC),它规定了内部的块级框如何排列。

块格式化上下文看似抽象,其实比较简单,它实际上就是页面上的一个块级元素,只是在布局上,该元素内部的元素和外部的元素相互独立,互不影响。

通俗的讲,就是在创建了块格式化上下文的元素中,其子元素都会按照块格式化上下文的规则排列自己。以下元素都会自动为其内容创建一个块格式化上下文:

  • 根元素
  • 浮动的元素(float: left | right)
  • 固定定位的元素(position: absolute | fixed)
  • overflow 属性值为 hidden | auto | scroll 的元素
  • display 属性值为 table | table-caption | table-cell | flex的元素
  • 表格的单元格(td、th)
  • 表格的标题(display: table-captions,caption)

块格式化上下文具有以下特点:

1)在块格式化上下文中,如果只存在块级框,则所有块级框从包含块的顶部开始,一个接一个地垂直排列,每个框被渲染为完整的一行。

假设在 body 下,有一个 class = "wrapper" 的 div 子元素,该子元素又包含三个 div 子元素:

 
  1. <html>
  2. <head><title>BFC</title>
  3. <body>
  4. <div class = "wrapper">
  5.     <div style = "height: 40px;"></div>
  6.     <div style = "width: 100px; height: 40px;"></div>
  7.     <div style = "width: 100px; height: 20px;"></div>
  8. </div>
  9. </body>
  10. </html>

上述代码中,html 元素是根元素,body 元素是根元素唯一的子元素,.wrapper 又是 body 的子元素。

为了便于观察,为根元素 html 设置了外边距、内边距和红色边框,为 body 元素设置了内边距和黑色边框,为 .wrapper 子元素设置宽度、内边距和蓝色边框,还为其子元素设置上下外边距和灰色边框:

 
  1. html {
  2.    margin: 10px;
  3.    padding: 10px;
  4.    border: 1px solid red;
  5. }
  6. body {
  7.    padding: 20px;
  8.    border: 1px solid black;
  9. }
  10. .wrapper {
  11.    width: 300px;
  12.    padding: 10px;
  13.    border: 1px solid blue;
  14. }
  15. .wrapper div {
  16.    margin: 10px 0;
  17.    border: 1px dashed gray;
  18. }

由创建BFC的条件可知,根元素默认会创建一个BFC,而 body 和 .wrapper 都不符合创建BFC的条件。因此,body、.wrapper 及 .wrapper 的三个子元素,都将参与根元素创建的块格式化上下文。

前面曾经介绍过,所有元素都是在其包含块中布局。由此可知,body 在初始包含块中布局,.wrapper 在 body 创建的包含块中布局,.wrapper 的三个子元素在 .wrapper 创建的包含块中布局,并从包含块的顶端开始,一个接一个地垂直排列。运行结果如图 5‑8 所示:

块格式化上下文中元素垂直排列图5-8 块格式化上下文中元素垂直排列

从上图可以看出,虽然 .wrapper 的第二个和第三个子元素的宽度都是 100px,它们也独占一行。由此可知,在BFC中,每个块级框始终独占一行,即便一行的空间足以容纳多个框也是如此。

2)在同一个块格式化上下文中,相邻两个框之间的垂直距离,由它们的垂直外边距计算得到。当两个垂直外边距相遇时,它们之间的垂直距离,不是第一个框的 margin-bottom 与第二个框的 margin-top 之和,而两者中的较大者。

在CSS中,把这个现象称作外边距合并,即 margin 的合并,意思是说较小的 margin,被合并到了较大的 margin 之中。如图 5‑9 所示:

相邻元素的垂直外边距合并图5-9 相邻元素的垂直外边距合并

外边距合并时,当两个相邻的外边距都是正数时,合并结果是两者中的较大者;都是负数时,合并结果是两者绝对值较大者;一正一负时,合并结果是两者之和。

只要是两个垂直外边距相遇,不管这两个元素之间是父子关系还是兄弟关系,都会发生外边距合并。当一个元素包含在另一个元素中时(假如没有内边距或边框把外边距隔开),它们相邻的外边距也会发生合并。如图 5‑10 所示:

父元素和子元素的外边距合并图5-10 父元素和子元素的外边距合并

一个元素自身的垂直外边距也可以发生合并,假设有一个空元素,它有上下外边距,但没有边框和内边距。这种情况下,上外边距与下外边距就碰到了一起,它们就会发生合并。如图 5‑11 所示:

元素自身的垂直外边距合并图5-11 元素自身的垂直外边距合并

外边距合并看上去似乎有点奇怪,但在页面布局中,它却有存在的现实意义。假设有一组块级框,它们都设置了相同上下外边距。如果没有外边距合并,第一个框和最后一个框之外的所有框之间的垂直外边距,都将是相邻上外边距和下外边距之和,这意味着这些框之间的空间将会加倍。如果发生外边距合并,框之间的上外边距和下外边距就合并,所有框之间的垂直距离就会保持一致。如图 5‑12 所示:

外边距合并使距离一致图5-12 外边距合并使距离一致

只有同一个块格式化上下文中,块级元素的垂直外边距会发生合并,而浮动元素或绝对定位元素属于不同的BFC,它们之间的外边距不会合并。

3)在块格式化上下文中,每个块级框的左外边界,都紧贴包含块的左内边界(对于从右往左的格式化,则为框的右外侧紧贴包含块右侧),即便存在浮动也是如此,除非这个块级框创建了一个新的BFC。

假设在一个容器中,有一个 div 子元素和一个段落子元素:

 
  1. <div class = "wrapper">
  2.     <div></div>
  3.     <p>在BFC中,每个框的左外边界紧贴…除非框创建了一个新的BFC。</p>
  4. </div>

为了方便查看容器中内容的对齐情况,为容器设置宽度、内边距和边框,并让div 向左浮动,为两个子元素设置不同的背景颜色:

 
  1. .wrapper {
  2.    width: 300px;
  3.    padding: 10px;
  4.    border: 1px solid #ccc;
  5. }
  6. .wrapper div {
  7.    float: left;
  8.    width: 60px;
  9.    height: 60px;
  10.    background: #f90;
  11. }
  12. p {
  13.    color: #fff;
  14.    background: #2595e5;
  15. }

上述代码的运行结果如图 5‑13 所示:

内部的框左对齐图5-13 内部的框左对齐

从上图可以看出,浮动框和非浮动框的左外边界,都紧贴包含块的左内边界。其实,这也容易理解,因为浮动框已经脱离文档流,它的块级兄弟元素,会无视浮动框的存在,尽量占满一整行,导致被浮动框覆盖。

正如上图 所示,这里的 p 元素仍然紧贴包含块的左内边界,导致段落被浮动框覆盖,而 p 元素中的文本所形成的行框却向右移动,并水平变窄来给浮动元素腾出空间。随着文本的增加,后面的文本又会紧贴包含块的左内边界,因为它不再受浮动框的影响,便无需再向右移动了。

有时候,可以利用这个特性来创建文本环绕的效果,但有时候,这种情况并非所愿。如果设置段落的左外边距,使 p 元素为浮动元素腾出空间,就不会被浮动元素覆盖。

不过,如果让段落创建一个新的BFC,也不会被浮动框覆盖(但是,p 元素所生成的框,会受浮动框影响而变窄)。如:

 
  1. p {
  2.    color: #fff;
  3.    overflow: hidden;
  4.    background: #2595e5;
  5. }

运行结果如图 5‑14 所示:

消除浮动元素的影响图5-14 消除浮动元素的影响

这里使用 overflow 属性来创建BFC,使 p 元素向右移动并水平变窄,来给浮动元素腾出空间,以便不被浮动元素覆盖。当然,在实际应用中,可以根据实际情况,选择任意合适的属性来创建BFC。

4)计算块格式化上下文的高度时,浮动元素也参与计算,也就是说,创建了BFC的元素,会根据子元素情况自动适应高度,可以让一个元素包含浮动元素。在 5.3.2 节将详细介绍如何利用这个规则来间接实现清理浮动的效果,这里不再赘述。

前面已经介绍,只有块级框会参与块格式化上下文,那么,当一个块格式化上下文中既有块级框,又有行内级框时,该如何布局呢?考虑以下HTML代码片段:

 
  1. <body>
  2. <div class = "wrapper">
  3.     some text
  4.     <div>div</div>
  5.     <span>span1</span>
  6.     <span>span2</span>
  7. </div>
  8. </body>

为了方便查看每一行的效果,为 div 和 span 设置边框,为 div 设置上下外边距:

 
  1. .wrapper div,
  2. .wrapper span {
  3.     border: 1px dashed #ccc;
  4. }
  5. .wrapper div {
  6.     margin: 10px 0
  7. }

运行结果如图 5‑15 所示:

块格式化上下文中包含块级元素和行内元素图5-15 块格式化上下文中包含块级元素和行内元素

从上图可以看出,块级框中的文本“some text”生成一个匿名块级框直接参与BFC,div 元素生成一个块级框直接参与BFC,而 span1 和 span2 元素生成的行框(相当于一个匿名块级框)再参与BFC。

综上所述,普通流中页面布局基本的规则为:首先,为根元素创建一个BFC,所有子元素参与到该BFC中。然后,任何子元素都可以根据需要创建新的BFC,它的所有子元素再参与到该BFC中。这样,通过BFC的层层嵌套,就可以构建出千变万化的布局效果。

关于作者

歪脖先生,十五年以上软件开发经验,酷爱Web开发,精通 HTML、CSS、JavaScript、jQuery、JSON、Python、Less、Bootstrap等,著有《HTML宝典》、《揭秘CSS》、《Less简明教程》、《JSON教程》、《Bootstrap2用户指南》、《Bootstrap3实用教程》,并全部在 GitHub 上开源。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值