BFC: 优化网页渲染的秘密利器

一、什么是 BFC

  1. BFC 全称 Block Formatting Context, 中文可译为 块级格式化上下文
  2. 对于浮动元素、绝对定位元素、非块级盒子的块级容器(inline-blocktable-cellstable-captions)、overflow 值不为 visiable 的块级盒子, 容器内部将创建新的 BFC
  3. 具备 BFC 特性的元素, 内部将形成独立的渲染区域, 可以看成是一个容器, 容器内的元素和外部元素互不影响
  4. BFC 内, 块容器从顶端开始垂直地一个接一个地排列, 两个容器之间的垂直的间隙是由他们的 margin 值所决定的, 在同一个 BFC 中, 两个相邻的 块级盒子 的垂直外边距会产生折叠, 注意这里说的是 块级盒子 是指 display 的值为 block 的块级容器, 如果一个容器是 block 一个是 inline-block 那么他们的 margin 是不会发生折叠(下面将会进行详细描述)

二、如何触发 BFC

  1. 根元素 <html> 自带 BFC 特性
  2. float 属性值不为 none
  3. overflow 属性值不为 visible(默认值)
  4. display 属性值为 table-cell table-caption inline-block flow-root 中的任何一个
  5. position 属性值不为 relativestatic

三、BFC 特性(应用场景)

3.1 BFC 内容器排列规律

  1. BFC 里面的容器都会以垂直方向排列, 并且两个相邻 块级容器 的上下 margin 会发生重叠
<style>
  .box{
    width: 100px;
    height: 100px;
    margin: 20px;
    border: 2px solid red;
  }
  .parent {
    display: flow-root;
  }
</style>
<div class="parent">
  <div class="box"></div>
  <div class="box"></div>
</div>

  1. BFCmargin 值合并只针对两个块级容器(display 的值为 block), 如下例子一个容器是 block 一个是 inline-block 那么他们的 margin 是不会发生合并
<style>
  .box{
    width: 100px;
    height: 100px;
    margin: 20px;
    border: 2px solid red;
  }

  .box1 {
    display: inline-block;
  }
  
  .parent {
    display: flow-root;
  }
</style>
<div class="parent">
  <div class="box box1"></div>
  <div class="box"></div>
</div>

  1. 上面例子中 box1 设置了 display: inline-block 会触发了 box1 容器的 BFC, 但是 box1 容器是否触发 BFC 并不会影响 margin 的合并, 主要是因为 margin 的合并现象只针对块级容器, 下面例子将 display: inline-block 修改为 overflow: hidden; 同样触发了 box1 容器 BFC, margin 依然发生重叠
<style>
  .box{
    width: 100px;
    height: 100px;
    margin: 20px;
    border: 2px solid red;
  }

  .box1 {
    overflow: hidden;
  }
  
  .parent {
    display: flow-root;
  }
</style>
<div class="parent">
  <div class="box box1"></div>
  <div class="box"></div>
</div>

3.2 BFC 解决 margin 穿透问题

依据: 当容器触发 BFC 那么该容器就将是独立的渲染控件, 容器内外元素不会相互影响

  1. margin 穿透现象: 如下演示代码, 子元素设置了 margin 但是 margin 并没有作用与父元素(和父元素间没有产生间距), 而是作用于父元素相邻的元素上
<style>
  .parent {
    background: rgba(255, 0, 0, 0.5);
  }

  .child {
    width: 100px;
    height: 100px;
    margin-top: 50px;
    background: rgba(0, 255, 0, 0.5);
  }
</style>
<div>这是和父元素相邻的元素</div>
<div class="parent">
  <div class="child"></div>
</div>

  1. 解决办法: 为父元素创建 BFC, 如此容器内外元素就不会产生干扰

补充: BFC 并不是解决 margin 穿透的唯一方法, 还可以通过为父元素设置 borderpadding 等方法来解决 margin 穿透

<style>
  .parent {
    display: flow-root;
    background: rgba(255, 0, 0, 0.5);
  }

  .child {
    width: 100px;
    height: 100px;
    margin-top: 50px;
    background: rgba(0, 255, 0, 0.5);
  }
</style>
<div>这是和父元素相邻的元素</div>
<div class="parent">
  <div class="child"></div>
</div>

3.3 BFC 解决子元素浮动, 容器高度塌陷问题

  1. 当子元素发生浮动的情况下, 浮动元素不再参与父元素高度的计算
<style>
  .parent {
    background: rgba(255, 0, 0, 0.5);
  }

  .child {
    float: left;
    width: 100px;
    height: 100px;
    background: rgba(0, 255, 0, 0.5);
  }
</style>
<div class="parent">
  parent
  <div class="child"></div>
</div>

  1. 解决办法: 触发父容器 BFC, 浮动元素将会参与父元素高度的计算
<style>
  .parent {
    display: flow-root;
    background: rgba(255, 0, 0, 0.5);
  }

  .child {
    float: left;
    width: 100px;
    height: 100px;
    background: rgba(0, 255, 0, 0.5);
  }
</style>
<div class="parent">
  parent
  <div class="child"></div>
</div>

3.4 解决兄弟容器和浮动元素重叠问题

  1. 当容器进行浮动时, 该浮动容器将和其兄弟容器进行重叠
<style>
  .parent {
    background: rgba(255, 0, 0, 0.5);
  }

  .float {
    float: left;
    width: 100px;
    height: 100px;
    background: rgba(0, 255, 0, 0.5);
  }
</style>
<div class="parent">
  <div class="float"></div>
  <div class="content">
    在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列, 
    两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的, 
    在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠, 
    注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器, 
    如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin` 
    是不会发生折叠(下面将会进行详细描述)
  </div>
</div>

  1. 解决办法: 只需要触发兄弟容器(非浮动容器)的 BFC 就能够解决重叠问题, 实现自适应双栏布局
<style>
  .parent {
    background: rgba(255, 0, 0, 0.5);
  }

  .float {
    float: left;
    width: 100px;
    height: 100px;
    background: rgba(0, 255, 0, 0.5);
  }

  .content {
    display: flow-root;
  }
  
</style>
<div class="parent">
  <div class="float"></div>
  <div class="content">
    在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列, 
    两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的, 
    在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠, 
    注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器, 
    如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin` 
    是不会发生折叠(下面将会进行详细描述)
  </div>
</div>

  1. 补充: 上面例子中如何设置两个容器的间距
  • 为浮动容器设置 margin-right
  • 为非浮动容器设置 padding-left
  • 为非浮动容器设置 margin-left, 主要这里的属性值要大于浮动容器宽度才有效果, 所以这里不推荐该方法
<style>
  .parent {
    background: rgba(255, 0, 0, 0.5);
  }

  .float {
    float: left;
    width: 100px;
    height: 100px;
    background: rgba(0, 255, 0, 0.5);

    /* margin-right: 20px; */
  }

  .content {
    display: flow-root;
    /* padding-left: 20px; */
    margin-left: 120px;
  }

</style>
<div class="parent">
  <div class="float"></div>
  <div class="content">
    在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列, 
    两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的, 
    在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠, 
    注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器, 
    如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin` 
    是不会发生折叠(下面将会进行详细描述)
  </div>
</div>

四、参考

  1. CSS深入理解流体特性和BFC特性下多栏自适应布局
  2. 快速了解CSS display:flow-root声明
  3. 块格式化上下文
  4. 深入理解BFC和Margin Collapse

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值