clear与BFC对浮动的影响

1,370 阅读6分钟
原文链接: github.com

写在最前

本次是一个基础不能再基础的复习贴。旨在了解人人皆知的浮动,以及通过clear与bfc清除浮动的一些规范上的解释。
PS:下文没有css样式,全部通过语义化class来表示,因为我发现po一大堆css真是“又臭又长”还懒得看=。=

欢迎关注我的博客,不定期更新中——

划重点

本次主要再复习下三个知识点:

  • 众人皆知的浮动做了什么
  • clear做了什么
  • bfc做了什么

浮动

float CSS属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动中移除,尽管仍然保持部分的流动性(与绝对定位相反)。

基础效果大家都是熟悉的不能再熟悉了,在这些特性中有一点要牢记就是元素从页面常规流中移除了,其他元素无法感知到它的存在,但是文本和内联元素可以环绕它。可以看下两个例子来复习一下float产生的效果:

<div class="border">
    <div class=" div red left"></div>
    <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>

image

我们会发现,虽然红div下面是一个div是块级元素但由于浮动元素特性,导致下面的div中的文字产生了环绕效果,好像可以感知红div边界一样。这也算是保持了部分的流动性,因为如果我们像下面这样写,结果就有所区别了:

<div class="border">
    <div class=" div red absolute"></div>
    <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>

image

绝对定位的元素同样脱离了文档流,但是它真是完完全全脱离了,连文字都不认识它了哦。 同样,如果浮动元素下面的元素不是文字的话,效果就会和我们平时所见的那样:

<div class="border">
    <div class=" div red left"></div>
    <div class="div2 green"></div>
</div>

image

最常见的情况:普通的文档流的元素并不能感知到float的存在。从而也就会引发很经典的浮动导致父元素高度塌陷的问题:

<div class="border">
    <div class=" div red left"></div>
    <div class=" div green left"></div>
    <div class="div blue left"></div>
</div>

image

很经典的问题:父元素高度没了!那么我们要怎么做?恢复父元素高度咯!

clear

刚接触前端的时候就开始学清除浮动,清除浮动。但是清除浮动的这个核心clear,到底做了什么?

clear CSS 属性指定一个元素是否可以在它之前的浮动元素旁边,或者必须向下移动(清除浮动) 在它的下面。clear 属性适用于浮动和非浮动元素。

划重点:clear只是指定了一个元素是放在之前浮动元素旁边还是另起一行。这个和我们父元素没高度看似好像没啥关联。但是这么用了貌似就恢复了父级高度即清除浮动。看下示例代码:

<div class="border">
    <div class=" div red left"></div>
    <div class=" div green left clear"></div>
    <div class="div blue left"></div>
</div>

image

上面的例子确实用到了clear,但是父级高度并没有恢复。原因在于其中每个元素都设置了浮动。而clear也只是让其中一个元素并不在上一个浮动元素旁边,而是换行了,但这并不是我们想要的效果。因为clear做的并不是真的清除了浮动,只是“换了个行”。浮动本身还是存在的,全部脱离文档流。故上图中的父级高度仍然为0。

那么到底是什么恢复了父级的高度?

看下这个例子

<div class="border">
    <div class=" div red left"></div>
    <div class=" div green clear"></div>
    <div class="div blue left"></div>
</div>

image

可以看到在绿div中设置了clear但是没有设置float,我们恢复了父级的高度。从而说明“清除浮动”背后所做的,恢复父级高度,就是在浮动元素下方安插一个正常文档流的元素,这样父元素计算高度的时候会对其进行包裹,那么高度自然就计算出来了。

以此我们就可以了解到,市面上对于清除浮动(恢复父级高度)的方式,如果用到了clear,其核心思路就是安插一个正常文档流节点在最后,并且换行。原因自然是不换行(clear)的话,正常文档流感知不到浮动存在,计算的高度会少浮动元素的高度。

bfc

通过clear的方式确实可以恢复父级高度,那么还有没有别的方式呢?好的bfc。

什么是bfc?

一个块格式化上下文(block formatting context) 是Web页面的可视化CSS渲染出的一部分。它是块级盒布局出现的区域,也是浮动层元素进行交互的区域。

对于bfc的细节就不细说了,百度上有很多介绍的都很一致的文章了,随意看一篇。大体来说,bfc创建了一个自己的块,不干扰别人,别人不干扰它,同时这次关于恢复父级高度,我们只需要用到下图关于bfc的一个特性就可以了:
image
附规范地址( www.w3.org/TR/CSS2/vis…

简单来说就是,触发了bfc的元素,在计算高度的时候包括浮动元素。那么结果就很明了了。我们只需要对父级元素触发bfc就好了,触发方式如下:

  • 根元素或其它包含它的元素
  • 浮动元素 (元素的 float 不是 none)
  • 绝对定位元素 (元素具有 position 为 absolute 或 fixed)
  • 内联块 (元素具有 display: inline-block)
  • 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)
  • 具有overflow 且值不是 visible 的块元素,
  • display: flow-root
  • column-span: all 应当总是会创建一个新的格式化上下文,即便具有 column-span: all 的元素并不被包裹在一个多列容器中。

举一个最基本的overflow的例子:

<div class="border overflow">
    <div class=" div red left"></div>
    <div class="div green left"></div>
</div>

image

很明显高度一定会恢复。

小结

在最初接触前端的时候,一直可能会被清除浮动误导,以为clear就是清除了浮动,但其实clear并没有这个操作。要知道我们所做的一切都是围绕如何恢复父级元素的高度来做的就好,至于方法已经说过啦,就是面试前背的一大堆。

最后

惯例po作者的博客,不定时更新中——
有问题欢迎在issues下交流。