对BFC的简单理解

747 阅读3分钟

对BFC的简单理解

🙋 Hello,I'm IamZJT!
✍️ 一名菜鸟前端开发工程师!

📦 Github地址:iamzjt-front-end
🖐️ 欢迎 点赞 star,期盼与您并肩前行...

一、什么是BFC?如何应用?

  • (Block formatting context) 块级格式化上下文;
  • 一块独立渲染区域,内部元素的渲染不会影响边界以外的元素;
  • 形成BFC的常见条件: float不是none; position是absolute或fixed; overflow不是visible; display是flex inline-block等;
  • 常见应用:利用BFC避免margin重叠、自适应两栏布局、清除浮动。

二、BFC的特性和应用举例:

2.1 利用BFC避免margin重叠

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

20200731112131.png

从效果上看,因为两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 100px,而不是 200px。

首先这不是 CSS 的 bug,我们可以理解为一种规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>防止margin重叠</title>
</head>
<style>
	.container {
    	overflow: hidden;
	}
	
	p {
    	width: 100px;
    	height: 100px;
    	background: lightblue;
    	margin: 100px;
	}
</style>
<body>
	<div class="container">
        <p></p>
	</div>
	<div class="container">
        <p></p>
	</div>
</body>
</html>

这时候,两个盒子边距就变成了 200px

20200731112136.png

2.2 自适应两栏布局

根据:

  • 每个盒子的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
  .left {
    height: 100px;
    width: 100px;
    float: left;
    background: lightblue;
  }

  .right {
    height: 300px;
    background: #eee;
  }
</style>

<body>
  <div class="left">我是一个左浮动的元素</div>
  <div class="right">我是一个没有设置浮动, 也没有触发 BFC 元素</div>
</body>
</html>

20200731115454.png

这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:

20200731115519.png

这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度。

2.3 清除浮动

当我们不给父节点设置高度,子节点设置浮动的时候,会发生高度塌陷,这个时候我们就要清除浮动。

比如这样:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>清除浮动</title>
</head>
<style>
    .parent {
    	border: 1px solid #000;
    }
    
    .child {
    	width: 100px;
    	height: 100px;
    	background: #eee;
    	float: left;
    }
</style>
<body>
    <div class="parent">
        <div class="child"></div>
    </div>
</body>
</html>

20200731112145.png

由于容器内元素浮动,脱离了文档流,所以容器只剩下 2px 的边距高度。如果使触发容器的 BFC,那么容器将会包裹着浮动元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>清除浮动</title>
</head>
<style>
    .parent {
        border: 1px solid #000;
        overflow: hidden
    }
    
    .child {
        width: 100px;
        height: 100px;
        background: #eee;
        float: left;
    }
</style>
<body>
    <div class="parent">
        <div class="child"></div>
    </div>
</body>
</html>

20200731112148.png

扩展1:清除浮动有哪几种常见方法?

  • 额外标签法,在子元素的末尾加上一个标签(<div style="clear: both"></div>),其中要求这个标签必须是块级元素;

  • 父级添加overflow属性:auto、hidden、scroll;

  • 父级添加after伪元素;

    .clearfix::after {
    	content: "";
    	display: block;
    	clear: both;
    }
    
  • 父级添加双伪元素

    .clearfix::before, 
    .clearfix::after {
    	content: "";
    	dispaly: table;
    }
    
    .clearfix::after {
    	clear: both;
    }
    

扩展2:

上面写到了两栏自适应布局,也就是左侧固定,右侧自适应布局,目前我有两个思路。
思路1:跟上面一样,给右侧元素添加overflow:hidden,形成BFC;
思路2:从圣杯布局中启发而来,将left和right一起放进container盒子中,左侧盒子float:left浮动,然后给container设置padding-left值,最后给left设置margin-left负值,大功告成。
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>左侧固定,右侧自适应</title>
  <style>
    .left {
      width: 200px;
      height: 100px;
      background-color: pink;
      float: left;
      margin-left: -200px;
    }

    .right {
      width: 100%;
      height: 500px;
      background-color: skyblue;
    }

    .container {
      padding-left: 200px;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="left">这是左侧</div>
    <div class="right">这是右侧</div>
  </div>
</body>

</html>

ps

🎯 如果您看到这里,请不要走开。
🎉 这是一个早起俱乐部:三更灯火五更鸡

⭐️ 寻找 志同道合 的小伙伴,我们一起 早起