飞道的博客

CSS面试高频题之什么是BFC

528人阅读  评论(0)

之前一段时间因为各种各样的事情一直都没有时间来写博客,但是因为要保证月更原创的量也是只能翻出前几年压箱底的Java学习笔记了 ==|,当然笔者的博客还是以记录前端开发方面的知识为主的。

如题,笔者近期回顾了之前的面试经历,发现各个公司的面试问题虽然各有不同但是也有很多高频面试题,基本上都会问,甚至给我的感觉是面试官突然不知道问点什么好了他可能就会问到这些传统高频题。比如上次笔者面字节跳动(一面,凉的很彻底…以后会好好总结一下过程)面试官在问CSS的时候就问到了什么是BFC,其实这个问题在各种面经中都会看到,几乎可以说是要被问烂的题目。但是你别说,还是能问倒一些人,比如我…感觉BFC是笔者的一个知识盲区。

笔者总结了一下为什么关于BFC的问题没有答好:一方面是因为面试前准备不足,像BFC相关知识几乎是必考题没有复习到位;另一方面是关于BFC的用途比较隐晦,我们在写CSS的时候有时候触发了BFC的一些特性可能自己都没注意到,这也是BFC容易被忽视的原因之一。当然了解、掌握BFC对CSS开发还是很重要的,下面将详细介绍下BFC。

 

1. BFC的概念:

BFC,块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

2. 如何触发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、row、tbody、thead、tfoot的默认属性)或 inline-table
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素
  • contain 值为 layoutcontent或 paint 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1
  • column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更Chrome bug)。

 

3. 具体实例

以上关于BFC概念的介绍比较抽象,我们举一些具体的例子来看

首先就是在面试过程中,我们经常会被问到BFC是什么,有哪些方式可以触发BFC,这时候我们只需要记下常用的几种回答就好了,但是千万不要记错了,如果记错了或者没有记得很清楚不确定的话被厉害的面试官反问就尴尬了。一般只需要回答这几个:(1)浮动元素(2)position为absolute或fixed的(3)display为inline-block, table-cell, table-caption, table(table系的) 等(4)overflow 为hidden scroll auto inherit的(5)弹性布局(flex系)(6)网格布局(grid系)就可以了。其中浮动元素现在我们实际开发中几乎已经不用了(除了维护一些古老的项目),另外的几个包括固定定位、绝对定位、弹性布局、overflow都是开发中非常常见的属性,网格布局则是未来的一种大势所趋,在一些国外的网站上会经常见到。

① 外边距塌陷

有这样的一种面试题:外边距塌陷是什么现象(当块级元素(block)的上外边距(margin-top)下外边距(margin-bottom)同时都有设定时只会只会保留最大边距,这种行为称为边界折叠(margin collapsing )=> 怎么解决(触发BFC)=> BFC 是什么 => 怎样才能触发BFC => 你提到position为absolute何fixed可以触发BFC,relative可以吗 => 弹性布局是怎样的 => 网格布局是怎样的……具体例子如下:


  
  1. <div class="div1"> </div>
  2. <div class="div2"> </div>

  
  1. .div1 {
  2. width: 100px;
  3. height: 100px;
  4. background: red;
  5. margin-bottom: 50px;
  6. }
  7. .div2 {
  8. width: 200px;
  9. height: 200px;
  10. background: yellow;
  11. margin-top: 100px;
  12. }
如图所示:按照我们一般的想法这里div1和div2之间的距离应该是100 + 50,但实际计算的时候是取margin值更大的作为距离,这就是css盒子外边距合并

  
  1. <div class="wrapper">
  2. <div class="div1"> </div>
  3. <div class="div2"> </div>
  4. </div>

  
  1. .wrapper {
  2. display: flex;
  3. flex-direction: column;
  4. }
  5. .div1 {
  6. width: 100px;
  7. height: 100px;
  8. background: red;
  9. margin-bottom: 50px;
  10. }
  11. .div2 {
  12. width: 200px;
  13. height: 200px;
  14. background: yellow;
  15. margin-top: 100px;
  16. }
如上图所示:在div1和div2两个盒子外包裹了一个弹性布局的盒子,将主轴方向改为column,外边距合并的现象消失了,这是因为弹性布局触发了BFC,网格布局同理

 

② 两栏布局/三栏布局

两/三栏布局在我们进行pc端的web页面开发时比较常见,实现的方式有很多,如今比较流行的是利用flex弹性布局进行两栏布局,简单好用;但是在flex布局还没有出现/兼容性不佳的上古时代,一般都是通过float浮动来实现两栏布局的。这里就会涉及到浮动元素会覆盖正常文档流的元素(浮动元素脱离了文档流) ,例子如下:


  
  1. <div class="div1"> </div>
  2. <div class="div2">
  3. <div class="sub-cls"> </div>
  4. </div>

  
  1. .div1 {
  2. float: left;
  3. width: 200px;
  4. height: 200px;
  5. background: red;
  6. /* margin-bottom: 50px; */
  7. }
  8. .div2 {
  9. /* width: 800px; */
  10. height: 200px;
  11. background: pink;
  12. /* margin-left: 120px; */
  13. /* margin-top: 100px; */
  14. }
  15. .sub-cls {
  16. width: 50px;
  17. height: 50px;
  18. background: yellow;
  19. }
如图所示,浮动元素div1将sub-cls覆盖了,此时如果div1的宽度是固定的我们可以考虑给div2一个margin-left,当然,也可以使div触发BFC

  
  1. .div2 {
  2. overflow: hidden; /*触发bfc */
  3. /* width: 800px; */
  4. height: 200px;
  5. background: pink;
  6. /* margin-left: 120px; */
  7. /* margin-top: 100px; */
  8. }
div2触发BFC后,不会再有被div1覆盖的地方,sub-cls也就显示出来了,这样也不用考虑div1宽度的问题

 

 ③ 清除浮动

其实这一点没什么好说的,因为如前所述浮动是属于上古时代的css布局写法,使用它进行布局有很多的副作用(唯一的好处的兼容性良好,因为足够老…)和与之衍生的大量黑科技,比如清除浮动,圣杯、双飞翼布局……清除浮动是因为使用浮动会出现塌陷的情况:


  
  1. <div class="wrapper">
  2. <div class="div1"> </div>
  3. <div class="div2">
  4. <div class="sub-cls"> </div>
  5. </div>
  6. </div>

  
  1. .wrapper {
  2. width: 100%;
  3. border: 2px solid black;
  4. /* display: flex; */
  5. /* flex-direction: column; */
  6. /* align-items: center; */
  7. }
  8. .div1 {
  9. float: left;
  10. width: 200px;
  11. height: 200px;
  12. background: red;
  13. /* margin-bottom: 50px; */
  14. }
  15. .div2 {
  16. /*创建bfc */
  17. /* overflow: hidden; */
  18. float: left;
  19. width: 800px;
  20. height: 200px;
  21. background: pink;
  22. /* margin-left: 120px; */
  23. /* margin-top: 100px; */
  24. }
  25. .sub-cls {
  26. /* float: right; */
  27. width: 100px;
  28. height: 100px;
  29. background: yellow;
  30. }
如图所示,因为wrapper的子元素div1和div2都是浮动元素(脱离了文档流)所以无法撑开父盒子的高度,所以这里要利用BFC的特性清除掉浮动的副作用

 

修改wrapper的样式,使其触发BFC:


  
  1. .wrapper {
  2. /*创建bfc */
  3. overflow: hidden;
  4. width: 100%;
  5. border: 2px solid black;
  6. /* display: flex; */
  7. /* flex-direction: column; */
  8. /* align-items: center; */
  9. }
撑开了父盒子

 

 4. 总结

在flex,grid等新兴布局流行的今天,触发BFC进行元素布局的用法并不很多,主要体现在盒子外边距合并方面,而其他的类似清除浮动等用法比较少见,但是BFC的概念及其触发条件是我们必须要掌握甚至是背诵下来的。

 

 

参考:

https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context

https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

https://codepen.io/zitonzong/pen/BaodqvB

https://www.cnblogs.com/chen-cong/p/7862832.html

https://www.cnblogs.com/chencyl/p/3948331.html

 

 

 

 

 

 


转载:https://blog.csdn.net/a715167986/article/details/105855147
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场