你可以再问一次什么是BFC吗

501 阅读3分钟

块级格式化上下文(block formating context),是web页面的可视css渲染的一部分,是块盒子布局发生过程中的区域,也是浮动元素与其他元素发生交互的区域。

用更好理解一点的话来说,通过某些特定的方式可以创建一个块级格式化上下文盒子,在这个盒子内部形成了一个区域,区域内的元素不会干扰外界的其他区域,也不受外界的样式影响。

那么,怎样创建一个BFC区域呢?通过以下方式可以创建块级格式化上下文:

常见的BFC

  • 根元素,即html
  • 浮动元素,即元素的float树形不为none
  • 浮动定位元素,即元素的position是absolute、fixed
  • 行内块元素,即display为inline-block的元素
  • overflow属性不是visible的元素
  • 弹性盒子
  • 表格单元格,即tr、td以及display为table-cell的元素
  • 表格标题

还有些其他的不常用,就不列举出来了。

BFC的特性

边距重叠的现象

同一个BFC元素内的块级元素会发生边距重叠现象,看一段html示例

<!DOCTYPE html>
<html lang="en">
<head>    
<meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>   
    div {   
        width: 100px;  
        height: 100px; 
        margin: 100px;  
        background: #1890ff;  
        }
</style>
<body>   
    <div></div>
    <div></div>
</body>
</html>

上面2个div出在根元素body下边,body默认是bfc元素,因此,bfc中的两个块级元素div发生了外边距margin重叠的情况:

BFC区域不会与浮动元素重叠

如果一个元素是BFC,那么,它不会跟它旁边的浮动元素发生重叠,而是按顺序依次排列,看下示例:

首先演示一下,非bfc元素与浮动元素的布局情况

<style>
    .flow-div {
        float: left;
        width: 100px;
        height: 100px; 
        background: aqua;
    }
    .not-bfc-div {
        width: 200px;
        height: 200px;
        background: bisque;
    }
</style>

<body>
    <div class="flow-div"></div>
    <div class="not-bfc-div"></div>
</body>

可以看到,not-fbc-div这个盒子由于不是bfc,所以,它跟浮动元素flow-div发生了重叠

怎样取消这种情况?通过修改not-bfc-div的属性,增加overflow:hidden或者display:inline-block,使其变成BFC即可。

<style>
    .flow-div {
        float: left;
        width: 100px;
        height: 100px; 
        background: aqua;
    }
    .bfc-div {
        overflow: hidden;
        width: 200px;
        height: 200px;
        background: bisque;
    }
</style>

<body>
    <div class="flow-div"></div>
    <div class="bfc-div"></div>
</body>

这时可以看到,BFC与浮动元素不再重叠:

BFC解决了哪些问题?

浮动元素周边的文字环绕

<style>
    .flow-div {
        float: left;     
        width: 100px;
        height: 100px;
        background: aqua;   
    } 
    .not-bfc-div {
        /* overflow: hidden; */ 
        width: 200px;      
        height: 200px;   
        background: bisque;   
        white-space: pre-wrap;  
    }
</style>
<body> 
<div>     
   <div class="flow-div">12</div>        
    <div class="not-bfc-div">子元素浮动,父元素高度塌陷 外边距塌陷  浮动元素周围文字环绕问题子元素浮动,父元素高度塌陷 外边距塌陷  浮动元素周围文字环绕问子元素浮动问</div>  
</div>
</body>

可以看到,非BFC元素文字围绕着浮动元素布局展示:

将not-bfc-div改成BFC

<style>
    .flow-div {
        float: left;
        width: 100px;        
        height: 100px;
        background: aqua;    
    }   
    .bfc-div {  
        overflow: hidden;
        width: 200px;
        height: 200px;
        background: bisque;
        white-space: pre-wrap;   
    }
</style>
<body>
    <div>  
        <div class="flow-div">12</div>
        <div class="not-bfc-div">子元素浮动,父元素高度塌陷 外边距塌陷  浮动元素周围文字环绕问题子元素浮动,父元素高度塌陷 外边距塌陷  浮动元素周围文字环绕问子元素浮动问</div>  
    </div>
</body>

此时,文字将不再环绕着浮动元素布局:

解决浮动元素导致父元素高度塌陷的问题

当一个父元素内部的子元素有浮动属性时,该父元素的高度将不会被子元素撑开:

<style>   
    .outer {  
        background: blueviolet;
        border: 1px solid;   
 }
    .not-bfc-div {   
        float: left;    
        width: 200px;    
        height: 200px;   
        background: bisque;      
        white-space: pre-wrap;  
    }
</style>
<body> 
    <div class="outer"> 
        <div class="not-bfc-div"></div> 
    </div>
</body>

可以看到,该父元素的高度仅仅由于1px的边框而产生了2px的高度:

将父元素改为BFC之后。(注意,这里是将父元素改为BFC,这样,当父元素计算高度时,子元素即时是浮动元素,也会参与父元素的高度计算):

可以看到,紫色的父元素的高度已经被子元素撑开,高度变成了子元素的高度加上自身的border宽度。

两栏自适应布局

后面将不再展示代码,只直接将方法。

方法:两个div在同一水平上需要横向展示,并且一个固定宽度并设置float:left,一个自适应时,给固定的元素设定固定的宽度,给自使用的元素开启BFC即可。

原理:BFC的区域不会与float元素发生重叠。