[css] 一篇文章理解BFC

43 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

一、防止高度塌陷(4种方案)

问题重现

  • 父元素的高度,都是右内部未浮动子元素的高度撑起

问题重现

  • 子元素浮动,还会对父元素造成影响。

  • 如果子元素浮动起来,就不占用普通文档流的位置。父元素高度就会失去支撑,也称为高度坍塌

解决: **防止高度坍塌,**4种方案:

  • 方案一:为父元素设置overflow:hidden属性。

  • 原理: CSS中的overflow :hidden属性会强制要求父元素必须包裹住所有内部浮动的元素,以及所有元素的margin范围

  • 缺点,如果刚好父元素有些超范围的子元素内容需要显示(比如,个 别position定位的子菜单项),不想隐藏,就会发生冲突。

  • 方案二: 在父元素内的结尾追加一个空子元素(块级元素),并设置空子元素清除浮动影响(clear:both) 。

  • 缺点: 无端多出一个无意义的看不见的空元素,影响选择器和查找元素

  • 方案三: 设置父元素也浮动。

  • 原理: 浮动属性也会强制父元素扩大到包含所有浮动的内部元素

  • 缺点: 会产生新的浮动影响。比如,父元素浮动,导致父元素之后平 级的页脚div上移,被父元素挡住了

  • 解决: 设置父元素之后的平级元素清除浮动(clear:both)

  • 完美解决: 为父元素末尾伪元素设置clear:both

  • 问题:个别浏览器,display:table,可能带默认高度

  • 保险起见: 再加一个属性height:0px

总结

image-20220818192446804

为什么overflow和float会强制父元素包裹浮动的子元素?

二、BFC

  • BFC(Block formatting context)
  • 直译为"块级格式化上下文"。
  • 它是网页中一个独立的渲染区域( 也成为formatting context )。
  • 这个渲染区域只有块级(Block)元素才能参与
  • 规定内部的块级元素如何布局
  • BFC渲染区域内部如何布局,与区域外部毫不相干
  • 外部元素也不会影响BFC渲染区域内的元素

什么是BFC

  • 简单说:BFC就是页面上的一个隔离的独立渲染区域。

  • 区域里面的子元素不会影响到外面的元素。

  • 外面的元素也不会影响到区域里面的子元素。

image-20220818194738318

2种渲染区域(Formatting Context)

image-20220818194900055
  • BFC(block fomatting context)

    • 块级元素渲染区域:所有display 属性为 block, list-item, table 的元 素,会生成块级元素渲染区域。
    • 块级元素渲染区域内以BFC( block fomatting context)方式渲染;
  • IFC( inline formatting context)

image.png

重点 4种情况会形成BFC区域

  • foat的值不是none

  • position的值不是static或者relative (position 的值是 fixed、absolute;)。

  • 非块级元素: display的值是inline-block、table-cell、flex、table-caption或者 inline-flex

  • 块级元素: overflow的值不是visible

所以 形成BFC区域可以解决高度坍塌!

BFC 解决什么问题

1、解决高度坍塌

2、避免垂直方向 margin合并

3、避免垂直方向 margin溢出

4、左固定右自适应布局

1、解决高度坍塌

(如上面解析)

2、避免垂直方向 margin合并

问题重现:

  • 垂直方向上,两个元素上下margin相遇时,两元素的间的总间距并 不等于两个margin的和。而是等于最大的margin。
  • 小的margin会被大的margin吞并。

解决:

step1: 用一个外围块元素包裹下方元素

step2:(如下避免垂直方向 margin溢出 的解决方式)

3、避免垂直方向 margin溢出

问题重现

  • 问题:子元素设置margin-top,会超出父元素上边的范围,变成父 元素的margin-top。
  • 而实际上,子元素与父元素之间,依然是没有margin-top的

解决

  1. 设置父元素overflow:hidden

    原理: 父元素变成BFC渲染区域,就必须包裹内层子元素的margin

    缺点: 为如果父元素中部分自由定位的子元素,希望即使超出父元 素范围,也能显示时,就冲突了。

    1. 父元素透明(transparent)边框

    原理: 这里不是bfc。而是因为边框本身可以阻隔margin溢出。

    缺点: 边框会增大父元素的实际大小,导致布局错乱。

    1. 父元素的padding-top代替第一个子元素的margin-top

    原理: 这里也不是bfc。而是因为padding本身可以阻隔margin溢出。

    1. 父元素内第一个子元素前添加一个空的BFC元素,例如

    原理: table的display属性默认相当于table,所以形成小的bfc渲染区 域。其他元素的margin不能进入table范围内。就阻隔了margin向上 溢出。

    优点: 空table元素没有大小,不占用父元素控件。

    缺点: 增加一个看不见的空元素,干扰查找元素

    1. 最好的解决: 父元素::before{ content:""; display:table; }

    原理: display:table,在子元素之前形成平级的bfc渲染区域。不允许子元素的margin进入::before范围内。

    优点:既不隐藏内容,又不添加新元素,又不影响高度。

4、左定宽,右自适应布局

image-20220824105309847

第一步: 左边定宽元素左浮动: 左{ float:left; width:固定宽 }

第二步: 右边元素不用右浮动,而是右{overflow:hidden; ... }

原理: 右边元素overflow:hidden后,形成BFC渲染区域。左边的float 元素就不能进入右边范围了。