学习JS原理之BFC

819 阅读7分钟

CSS 定位机制

CSS 有三种基本的定位机制:普通流、浮动和绝对定位。

普通流

除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。

块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。

行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line Box),行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。

浮动

float 属性定义元素在哪个方向浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。

float: left|right|none|inherit;

position定位

任何元素都可以定位,不过绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。

float: absolute|fixed|relative|static|inherit;

什么是块级格式化上下文(BFC)

“BFC即 Block Formatting Contexts (块级格式化上下文), 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。”

如何触发BFC

  • body 根元素
  • 浮动元素:float 除 none 以外的值
  • 绝对定位元素:position (absolute、fixed)
  • display 为 inline-block、table-cells、flex、inline-flex、flow-root(没有副作用的方案,但需注意兼容性)、grid、inline-grid等
  • overflow 除了 visible 以外的值 (hidden、auto、scroll)

BFC的特性

1、内部的Box会在垂直方向上一个接一个的放置

2、垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠(塌陷),与方向无关。)

3、每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)

4、BFC的区域不会与float的元素区域重叠

5、计算BFC的高度时,浮动子元素也参与计算

6、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然

BFC的应用

清除浮动(同时说明特性3、特性5、特性6)

<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .child1 {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }
</style>

<body>
  <div class="content-box">
    <div class="child1"></div>
  </div>
</body>

  • 子元素浮动,脱离文档流,父元素高度只剩下border
<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
    overflow: hidden;  // 让父元素触发BFC
  }

  .child1 {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }
</style>

  • 触发父元素的BFC,父元素高度恢复,故计算BFC的高度时,浮动子元素也参与计算(特性5)

防止元素上下margin折叠(同时说明特性2、特性6)

<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .child {
    width: 200px;
    height: 200px;
    background: #FFA500;
    margin: 50px auto;
  }
</style>

<body>
  <div class="content-box">
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>

  • 两个子元素的上下外边距发生重叠,距离只差50px(应该为第一个子元素的bottom-margin+第二个元素的top-margin=100px)
<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .parent {
    overflow: hidden; // 将外边距折叠的元素放入两个不同的BFC容器中
  }

  .child {
    width: 200px;
    height: 200px;
    background: #FFA500;
    margin: 50px auto;
  }
</style>

<body>
  <div class="content-box">
    <div class="parent">
      <div class="child"></div>
    </div>
    <div class="parent">
      <div class="child"></div>
    </div>
  </div>
</body>

  • 将发生外边距重叠的子元素分别放入两个BFC容器中,每个BFC都是一个独立的容器

实现两栏布局

<style>
  .content-box {
    background: #fff;
    width: 300px;
  }

  .left {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }

  .right {
    background: #FF4500;
    color: #fff;
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。

      块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。

      行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line
      Box),行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。
    </div>
  </div>
</body>

  • 浮动元素会覆盖未浮动元素,但文字不会被覆盖。
<style>
  .content-box {
    background: #fff;
    width: 300px;
  }

  .left {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }

  .right {
    background: #FF4500;
    color: #fff;
    overflow: hidden; // 右侧未浮动元素,触发BFC
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
      块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。
    </div>
  </div>
</body>

  • 未浮动元素触发BFC,能避免被浮动元素覆盖

实现同等高度的两栏

<style>
  .content-box {
    background: #fff;
    width: 300px;
    overflow: hidden;

  }

  .content-box>div {
    /* 注意这里 */
    padding-bottom: 100000px;
    margin-bottom: -100000px;
  }

  .left {
    background: #fadc09;
    height: 300px;
    width: 100px;
    float: left;
  }

  .right {
    height: 100px;
    background: #faa509;
    display: flow-root;
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非专门指定,否则所有框都在普通流
    </div>
  </div>
</body>

总结

这让我想起上一次面试的时候,面试题就是让我实现这样的两栏布局,然而小菜鸟的我,还不是很理解BFC原理竟然用flex,然后写了好多样式,而且还及其不智能。哈哈哈~

以上三种对于BFC的应用都很普遍,再也不用新增新元素,用clear:both来清除浮动拉~

值得一说的是:就在我看了好多BFC相关的文章,学习了BFC相关的原理之后没几天,就有同事问我边距被压缩的问题,我一看就是边距重叠了,都没想就说你拿一个div包一下加个overflow:hidden啥的。瞬间感觉没有白学呀,感觉自己挺牛逼呀~虽然我知道我其实还是一个小菜鸟。哈哈哈~

但是我会继续努力哒~