CSS 格式化上下文详解

CSS格式化上下文

CSS 中很重要的一环就是 BFC 块级格式化上下文,本文整理了 CSS BFC 的相关知识,建议沐浴更衣后食用。

在正式讲解BFC之前,先了解一下浏览器外边距重叠的问题。

外边距重叠

MDN:块的上外边距(margin-top)和下外边距(margin-bottom)有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距折叠
注意:外边距重叠都是发生在块级元素中,设定 float 和 position=absolute 的元素不会产生外边距重叠行为。

有三种情况会形成外边距重叠:

  • 同一层相邻元素之间:相邻的两个元素之间的外边距重叠。box1和box2的margin为200px
<style>
  div {
    width: 100px;
    height: 100px;
    background-color: pink;
  }
  .box1{
    margin-bottom: 100px;
  }
  .box2{
    margin-top: 200px;
  }
</style>
<div class="box1"></div>
<div class="box2"></div>
  • 没有内容将父元素和后代元素分开:如果没有边框 border,内边距 padding,行内内容,也没有创建块级格式上下文就会出现父块元素和其内后代块元素外边界重叠,重叠部分最终会溢出到父级块元素外面。如下:wrapper 有 100px 的上外边距,而 box 和 wrapper 之间是没有 100px 的上外边距。
<style>
  .wrapper {
    width: 200px;
    height: 200px;
    background-color: pink;
  }
  .box{
    width: 100px;
    height: 100px;
    margin-top: 100px;
    background-color: powderblue;
  }
</style>
<div class="wrapper">
  <div class="box"></div>
</div>
  • 空的块级元素:如下示例,内容1 和 内容2 之间有200px的距离。
<style>
  div {
    margin-top: 100px;
    margin-bottom: 200px;
  }
</style>

<p>内容1</p>
<div></div>
<p>内容2</p>

格式化上下文

行内格式化上下文(Inline formatting context)

各行内框(inline boxes)一个接一个地排列,其排列顺序根据书写模式的设置来决定:

  • 对于水平书写模式,各个框从左边开始水平地排列
  • 对于垂直书写模式,各个框从顶部开始水平地排列
.horizontal {
  writing-mode: horizontal-tb; // 从左开始
}

.vertical {
  writing-mode: vertical-rl; // 从上开始
}

块格式化上下文

块格式化上下文(Block Formatting Context,BFC) 是 Web 页面的可视 CSS 渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。形成独立的渲染区域,内部元素的渲染不会影响外界。

总结来说具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。

触发BFC的条件「常见」
  • 根元素(< html >)
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block、table-cells、flex)
  • overflow 值不为 visible 的块元素 (hidden、auto、scroll)
BFC的特性
  • BFC是独立容器,容器内部元素不会影响容器外部元素。
  • 计算BFC的高度时,浮动元素也参与计算。
  • BFC的区域不会与float的元素区域重叠。

注意:很多博客都会将属于同一个BFC的两个相邻盒子的margin会发生重叠认为是BFC的特性,不是不是!没有触发 BFC 也是如此排列的。BFC 可以解决这种重叠,但对于margin重叠,我们通常不解决,合理利用就好了。

BFC的常用案例:
1、解决 margin 重叠
  • 相邻子元素的重叠

内部的盒子会在垂直方向上一个接一个的放置,垂直方向上的距离由margin决定。BFC可以避免margin折叠,例子:

<style>
  .wrapper{
    border: 1px solid black;
  }
  .box {
    width: 200px;
    height: 200px;
    background-color: #999;
  }
  .box1 {
    margin-bottom: 100px;
  }
  .box2 {
    margin-top: 200px;
  }
</style>

<div class="wrapper">
  <div class="box1 box"></div>
  <div class="box2 box"></div>
</div>

如下图,在普通文档流中,两个相邻容器的上下margin会重叠,并且取其最大的margin。

在这里插入图片描述

如果让其中一个盒子处于独立的BFC中,就不会重叠。如下图

在这里插入图片描述

<style>
  .wrapper{
    border: 1px solid black;
  }
  .wrapper2{
    overflow: hidden;
  }
  .box {
    width: 200px;
    height: 200px;
    background-color: #999;
  }
  .box1 {
    margin-bottom: 100px;
  }
  .box2 {
    margin-top: 200px;
  }
</style>

<div class="wrapper">
  <div class="wrapper2">
    <div class="box1 box"></div>
  </div>
  <div class="box2 box"></div>
</div>
  • 父子元素的margin重叠
<style>
  .wrapper{
    width: 200px;
    height: 200px;
    background: powderblue;
    overflow: hidden;
  }
  .box{
    width: 100px;
    height: 100px;
    margin-top: 100px;
    background: pink;
  }
  
</style>
<div class="wrapper">
  <div class="box"></div>
</div>

下图1为没有触发BFC,box的margin-top溢出到父元素。下图2为触发了BFC,内部的元素不会影响外部。
在这里插入图片描述
在这里插入图片描述

2、撑开float父元素高度

计算BFC的高度时,浮动元素也参与计算。可以用此撑开父元素。

<style>
  .wrapper{
    border: 1px solid black;
  }
  .box{
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
  }
</style>
<div class="wrapper">
  <div class="box"></div>
</div>

因为浮动会脱离普通流,形成浮动流,所以父级高度不会被子元素撑开。如下图

在这里插入图片描述

当触发BFC时,float元素会计入高度的计算中。

在这里插入图片描述

<style>
  .wrapper{
    border: 1px solid black;
    overflow: hidden;
  }
  .box{
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
  }
</style>
<div class="wrapper">
  <div class="box"></div>
</div>
3、可以清除浮动

BFC的区域不会与float的元素区域重叠。所以可以用来清除浮动

<style>
  .box1{
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
  }
  .box2{
    width: 200px;
    height: 200px;
    background: powderblue;
  }
</style>
<div class="box1"></div>
<div class="box2"></div>

结果如下图,可以看到,box2会和box1重叠出现。

在这里插入图片描述

当我们触发BFC之后,可以看到下图,并不会与float重叠

在这里插入图片描述

<style>
  .box1{
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
  }
  .box2{
    width: 200px;
    height: 200px;
    background: powderblue;
    overflow: hidden;
  }
</style>
<div class="box1"></div>
<div class="box2"></div>
4、实现两栏、三栏布局
  • BFC的区域不会与float的元素区域重叠。这个特性也可以实现两栏布局。给固定栏设置固定宽度,给不固定栏开启BFC。
<style>
  .left{
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
  }
  .right{
    height: 100px;
    background: powderblue;
    overflow: hidden;
  }
</style>
<div class="left"></div>
<div class="right"></div>

在这里插入图片描述

  • 三栏布局同理,左右固定,中间不固定。需要注意的是,center中间部分的div要放在left、right后面。
<style>
  .left {
    width: 100px;
    height: 100px;
    float: left;
    background: #ffc0cb;
  }
  .right {
    width: 100px;
    height: 100px;
    float: right;
    background: #ffc0cb;
  }
  .center{
    height: 100px;
    background: powderblue;
    overflow: hidden;
  }
</style>
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>

在这里插入图片描述

5、防止 float 文字环绕。

没啥卵用,但是这是一个用处。

<style>
  .left {
    width: 100px;
    height: 100px;
    background: #ffc0cb;
    float: left;
  }
  p{
    width: 200px;
    background: powderblue;
    overflow: hidden;
  }
</style>
<div class="left"></div>
<p>
  你好世界你好世界你好世界你好世界你好世界你好世界你好世界你好世界你好世界你好世界你好世界
</p>

我们经常用 float 来实现文字环绕的报纸效果,但如果你不想环绕…就可以触发 BFC 实现

在这里插入图片描述
在这里插入图片描述

希望对大家有用,记得点赞关注哦~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值