CSS浮动与BFC

110 阅读6分钟

文档流

在说浮动之前,先介绍一下文档流机制。

网页是一个多层的结构,通过CSS可以分别为每一层来设置样式。作为用户只能看到最顶上一层。这些层中,最底下的一层为文档流。文档流是网页的基础,我们所创建的元素默认都是在文档流中进行排列。

所以可以说网页中的元素主要有两个状态:

  • 在文档流中。
  • 脱离文档流。

block元素在文档流中的特点:

  • 默认宽度是继承父元素的宽度。
  • 默认高度是被内容(子元素)撑开。
  • 可以自定义宽高。
  • 在页面中独占一行,本质上是元素的内外边距、边框,width属性值的和要与父元素的宽度相等。
.box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
}

.box2 {
    width: 300px;
    height: 300px;
    background-color: orange;
}

以上代码box1的宽高只有200px,但是因为盒子模型的水平布局公式,所以box1默认添加了margin-right属性。所以box2无法位于box1的右边,而是排列在下面一行,这就是block元素独占一行的原理。 微信截图_20230102112205.png

inline元素在文档流中的特点

  • 从左往右排列,直到一行之中无法容纳当前元素时会换到第二行继续排列。
  • 无法定义宽高,宽高是由内容(子元素)撑开的。
  • 在页面中不会独占一行。

浮动

什么是浮动

浮动是通过设置float属性使元素脱离文档流,并且向其父元素的左侧或右侧移动。

元素脱离文档流的特点:

  1. 盒子水平布局的等式不再需要强制相等,意味着块元素不再独占一行。
  2. 块元素的默认宽度是被内容(子元素)撑开,不再是继承父元素的宽度。
  3. 行内元素会具备块元素的特性,可以定义宽高。

另外浮动元素还具有以下特性:

  1. 浮动元素在水平方向/垂直方向都不会超过它前面的浮动元素。
  2. 如果浮动元素的上面是一个没有设置浮动的块级元素,则浮动元素无法上移。
  3. 除了纯文本之外,行内元素/行内块元素/浮动元素/溢出隐藏/都可以识别浮动元素的位置。
  4. 块元素无法识别浮动元素,所以如果块元素在浮动元素下面,会直接覆盖其位置。

浮动最初是解决图片嵌入文本并自适应对齐的问题,因为纯文本是可以识别浮动元素的位置的,意味着文字不会盖住浮动元素,所以可以做出文字环绕的效果,现在常用于布局。

浮动.png

浮动引起的问题

子元素浮动以后完全脱离文档流,将会无法撑起父元素的高度,导致父元素高度塌陷。

比如以下父级元素box1是块级元素,子元素box2box3是浮动元素,无法撑开box1的高度。

微信截图_20230103193933.png

.box1 {
    border: 5px solid red;
    background-color: aquamarine;
}

.box2 {
    float: left;
    width: 200px;
    height: 200px;
    background-color: orange;
}

.box3 {
    float: left;
    width: 200px;
    height: 200px;
    background-color: pink;
}

父元素高度塌陷还会引起父元素的兄弟元素排版问题,导致页面布局混乱。比如以下代码中bottom-div是块级元素,无法识别浮动元素,但其中的纯文本可以识别浮动元素。

浮动问题.png

<div class="top-div">
    <div class="float-div">left</div>
    <div class="text-div">As much mud in the streets as if the waters had but newly retired from the face of the earth.</div>
</div>
<div class="bottom-div">As much mud in the streets as if the waters had but newly retired from the face of the earth,
     and it would not be wonderful to meet a Megalosaurus, forty feet long or so, waddling like an elephantine lizard up Holborn Hill.
</div>
<style type="text/css">
    .top-div {
        width: 500px;
        border: 2px solid black;
    }

    .float-div {
        float: left;
        width: 120px;
        height: 120px;
        border: 2px dotted red;
        color: red;
        margin: 10px;
    }

    .text-div {
        color: blue;
        border: 2px solid blue;
    }

    .bottom-div {
        width: 500px;
        height: 100px;
        margin: 5px 0;
        border: 2px dotted orange;
    }
</style>

清除浮动影响的方式

第一种方式是通过给目标元素添加clear属性,清除周围浮动元素对它的影响。原理是浏览器会自动为目标元素添加一个上外边距margin-top,使其位置不受其它浮动元素的影响。

clear属性的值可以是left(清除左侧浮动元素对当前元素的影响)、right(清除右侧浮动元素对当前元素的影响,both(清除两侧影响最大的那一侧)。clear的使用方式有以下几种:

  1. 直接给目标元素添加clear属性(此处清除了文字左侧的浮动影响),所以text-div元素跑到了float-left元素下边,又因为自动添加了一个margin-top属性,所以撑起了父元素的高度。
.top-div .text-div {
    clear: left;
    color: blue;
    border: 2px solid blue;
}

清除浮动1.png

  1. 在父元素top-div结束标签之前插入一个块级元素并且设置clear属性。
.top-div .blank-div {
    clear: both;
}

清除浮动2.png

  1. 在父元素中添加伪元素,注意伪元素行内元素,即使自动添加了margin-top属性也无法撑开父元素,所以用于清除浮动时需要转换为块级元素。
.top-div::after {
    content: "";
    display: block;
    // 必须是块级元素
    clear: both;
}
  1. clear的终极使用方式是给目标元素添加一个clearfix类,再给其添加伪元素并且设置clear属性。值得注意的是伪元素还可以通过设置dispaly: table;解决元素外边距合并的问题,所以综上所述常用代码如下:
.clearfix::before,
.clearfix::after {
    content: "";
    display: table;
    clear: both;
}

第二种方式是通过BFC特性清除浮动影响,比如给元素添加overflow属性可以使元素具备BFC特性,可识别浮动的子元素,所以可以解决高度塌陷问题,之后会解释什么是BFC。

  • 注意overflow的值不能为visibleclip
.top-div {
    width: 500px;
    border: 2px solid black;
    overflow: hidden;
}

BFC

什么是BFC

Block Formatting Context 块级格式化环境,是CSS中的一个隐式属性。

元素开启BFC后会变成一个独立的布局区域,并且具有以下特性:

  1. 不会被浮动元素覆盖。
  2. 子元素和父元素的外边距不会重叠。
  3. 可以包含浮动的子元素,不会导致高度塌陷。

如何让元素开启BFC特性

开启BFC的方式有很多种,但是所有开启BFC的方式有会有一些副作用,这里列出常用的一些方式。

  1. body本身就具备BFC特性
  2. 元素设置float属性。(不推荐)
  3. 通过display属性将元素设为inline-block元素。(不推荐)
  4. 元素设置overflow属性且值不为visibleclip
  5. 元素设置position属性,值为absolutefixed