关于BFC的理解
标签: css,BFC
关于BFC是在一篇技术帖中看到的,当时看得起荤八素。没有真正理解其中的原理及解决的问题。直到后来在工作中遇到BFC类似的问题,但是却没有意识到这是BFC类的问题,可能是之前文章没有认真看的缘故吧!而在最近看到清除浮动的问题,其中有提到BFC是一种清除浮动的方案,文章看完之后才发现原来之前工作中遇到的类似的问题可以这样解决,这居然就是BFC。所以觉得有必要记录下我对BFC的理解,浅浅的理解,欢迎来喷!
1.什么是BFC
  BFC(Block Formatting Context)直译为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
  大家都知道在css中,对于一个元素需要知道它的类型是block还是inline,因为在css中布局是以盒子为对象和基本单位,盒子类型的不同决定了不同的格式化上下文渲染方式。既然盒子的类型会影响网页中具体元素的布局,那么BFC又是怎么来影响盒子从而影响最终的布局的呢?
如何产生BFC
CSS2.1中规定满足下列CSS声明之一的元素便会生成BFC:
- 根元素
- float的值不为none
- overflow的值不为visible
- display的值为inline-block、table-cell、table-caption
- position的值为absolute或fixed
2.BFC的约束规则
浏览器对于BFC块区域的约束规则如下:
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
3.BFC的作用及原理
1)自适应两栏布局
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>BFC</title>
<style>
    *{margin: 0;padding: 0}
    body {
        width: 300px;
        position: relative;
    }
 
    .aside {
        width: 100px;
        height: 150px;
        float: left;
        background: #ff0000;
    }
 
    .main {
        height: 200px;
        background: #228B22;
    }
</style>
<body>
    <div class="aside"></div>
    <div class="main"></div>
</body>
</html>
页面:
“每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。”
虽然aside有浮动,但是aside和main左边产生了接触重叠,就如bcf规则的第四条。但我们可以通过触发main来产生bfc来实现两栏布局。
.main {
    overflow: hidden;
}
当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:
2)清除内部浮动
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>BFC</title>
<style>
    *{margin: 0;padding: 0}
    .main{
      width:300px;
      border:1px solid #666;
      padding:10px;
    }
    .inner-left{
      height:100px;
      width:100px;
      float:left;
      background:#f00;
    }
    .inner-right{
      height:100px;
      width:100px;
      float:right;
      background:#090;
    }
</style>
</head>
<body>
  <div class="main">
    <div class="inner-left"></div>
    <div class="inner-right"></div>
  </div>
</body>
</html>
页面:
为了消除内部浮动,我们可以触发main生成BFC,那么main在计算高度时,main内部的浮动元素也会参与计算。
.main {
    overflow: hidden;
}
清除后:
3)防止垂直 margin 重叠
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>BFC</title>
<style>
  .text{border: 12px solid #ddd}
  p {
      color: #f55;
      background: #228B22;
      width: 200px;
      line-height: 100px;
      text-align:center;
      margin: 100px;
  }
</style>
<body>
<div class="text">
  <p>test1</p>
  <p>test2</p>
</div>
</body>
</body>
</html>
页面:
两个p之间的距离为100px,发送了margin重叠。根据BFC布局规则:Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
  我们可以在p外面包裹一层容器,并触发该容器生成一个BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>BFC</title>
<style>
  .text{border: 12px solid #ddd;}
  .wrapper{overflow: hidden;}
  p {
      color: #f55;
      background: #228B22;
      width: 200px;
      line-height: 100px;
      text-align:center;
      margin: 100px;
  }
</style>
<body>
<div class="text">
  <p>test1</p>
  <div class="wrapper">
    <p>test2</p>
  </div>
</div>
</body>
</body>
</html>

4 特别注意
  需要特别注意的是在ie8以下的ie版本中,需要触发haslayout来实现类似的bfc的效果。 haslayout是 IE 浏览器渲染引擎的一个内部组成部分layout在渲染是会形成的一个属性,属性值可以为 true 或 false。 当一个元素的 ‘hasLayout’ 属性值为 true 时,我们说这个元素有一个布局(layout),或拥有布局。
一下元素会触发 hasLayout属性:
<html>, <body> <table>, <tr>, <th>, <td> <img> <hr> <input>, <button>, <select>, <textarea>, <fieldset>, <legend> <iframe>, <embed>, <object>, <applet> <marquee>
在开发过程中我们还可以通过设置css属性值来触发haslaout,最常做的方法是设置zoom:1。因为为元素设置 zoom: 1 既可以触发元素的 hasLayout 同时不会对元素造成多余的影响。
来源:https://www.cnblogs.com/marvinemao/p/4874890.html