清除浮动两种方法(使用clear属性与生成BFC)深入,让你明白为啥这样就可以清除浮动。

810 阅读8分钟

简单介绍一下什么是浮动以及浮动会带来什么影响

  • 浮动是啥: 通俗来说,是某元素设置了float属性,从而该元素会脱离标准文档流,浮动在父元素左右边界之内。

  • 浮动影响: 当元素浮动,该元素的高度不会自动撑起父元素的高度。(但大多数情况下这并不是我们想要的)

写在前面

清楚了浮动以及浮动带来的影响,更多情况下,我们希望的是浮动元素和普通元素行为方式大体相似,同时也能够产生左对齐或者右对齐的效果。所以至此我们需要来清除浮动

ps: 网络上大致会有清除浮动的方法,但是只是教会你如何用,但是更多的可能你并不清楚为什么这样他就会就能够清除浮动所带来的效果,其实在此文章之前我也是,哈哈哈,不过通过研究各路神仙的文章以及w3c,我将所整理的方法以及自己的见解放出来分享。

--------------------进入主题-------------------

方法一: 使用CSS属性clear:both, left, right

    <style>
        .contain {
            width: 50%;
            background-color: paleturquoise;
            margin-bottom: 120px;
        }

        .float-left {
            float: left;
        }

        .float-right {
            float: right;
        }

        .float {
            width: 60px;
            height: 60px;
            background-color: orange;
            margin: 0 10px;
        }

        .clear {
            width: 100px;
            background-color: orchid;
        }

        .clear-left {
            clear: left;
        }

        .clear-right {
            clear: right;
        }

        .clear-both {
            clear: both;
        }
    </style>
<body>
    <div class="contain">
        <div class="float float-left">浮动1-1</div>
        <div class='clear clear-left'>我来清除浮动1</div>
    </div>

    <div class="contain">
        <div class="float float-right">浮动2-1</div>
        <div class='clear clear-left'>我来清除浮动2</div>
    </div>

    <div class="contain">
        <div class="float float-right">浮动3-1</div>
        <div class='clear clear-right'>我来清除浮动3</div>
    </div>

    <div class="contain">
        <div class="float float-right">浮动4-1</div>
        <div class='clear clear-both'>我来清除浮动4</div>
    </div>

    <div class="contain">
        <div class="float float-right">浮动5-1</div>
        <div class='clear clear-both'>我来清除浮动5</div>
        <div class="float float-right">浮动5-2</div>
    </div>

    <div class="contain">
        <div class="float float-right">浮动6-1</div>
        <div class="float float-right">浮动6-2</div>
        <div class='clear clear-both'>我来清除浮动6</div>
    </div>
</body>
    
  • 效果图:

  • 先看图一(对应第一段div,图二三四五六暂且别管),大家有没有想过为什么这样就可以撑开父元素,清除浮动呢,首先让我们看一下w3c对clear的说明,上图:

"规定元素哪一侧不允许其他浮动元素"

这特么说实话,我能理解他想表达什么,但好像这句话似乎听着有些奇怪。

通常这样说话:我不允许我左边有人,那是不是左边的人得走开,而我不动,我就在这呆着。

换做这里难道是:我不允许左边有浮动元素,那么左边浮动元素你爱去哪去哪,只要别在我左边,我就在这里。

说到这里似乎是左边元素会做出某些操作,而本身元素不做什么操作,但是这样吗?(其实不是)

继续往下看

如果声明为左边或右边清除,会使元素的上外边框边界刚好在该边上浮动元素的下外边距边界之下。

重点来了:

"当前元素声明左右清除,会使元素的上外边框边界刚好在该边上浮动元素的下外边距边界之下。"

也就是说我不允许左侧(以左侧有浮动元素举例)有浮动元素,那我该怎么办,我动不了左侧浮动元素,那我自己动还不行吗,于是我就下去待着,我把头顶着刚才在我左边的那个浮动元素,这下好了,你不动我动。

如上面图1所示,"我来清除浮动1" 头顶着"浮动1-1"

当前"我来清除浮动1"是个普通元素,他通过给自己设置clear:left,让自己跑到原先在自己前面的(注意这里我用的词是前面)浮动元素下面待着,于是乎,父元素就会被撑开,没办法,谁让我有这么个儿子(儿子指代当前普通元素,因为还在标准文档流中,所以将父元素撑开)呢,至此,我们就利用clear属性实现了清除浮动。

但是还没完!(后面还有图二三四五六。。。)

---------------------------分割线---------------------------

图一是给当前元素设置clear:left(清除左浮动),清除的是左浮动元素(float:left)的效果,如果我们把当前浮动元素设置成右浮动呢?

见图二(对应第二段div),我们发现清除浮动失效了,在此,我们可以知道,给当前元素设置clear:left是清除float:left的浮动效果,如果需要清除float:right,name我们需要设置clear:right,见图三(对应第三段div)原理同上。

那么如果我们设置clear:both则不管左右浮动,都会生效,见图四(对应第三段div)。 但这样说并不准确,准确说法让我们看第五段div以及图五效果。

我们发现clear:both对第一个右浮动生效了,第二个右浮动似乎不是我们预期的结果。这里就是关键的地方,实际上clear属性只针对于设置了clear元素的前面的浮动元素,也就是代码位置前面的浮动元素,这也是为什么前文我要特地提及前面这个词,这样我们就可以很好理解,为什么看见大多数人使用clear:both都在浮动元素最后使用,因为这样才能清除所有浮动带来的效果,否则放在浮动元素中间(这里的最后,前面,中间指的都是代码位置),后面的浮动元素不会生效。见图六(放在最后设置clear:both/left)清除所有元素浮动。

这里也很好的解释了为什么我们都给伪元素after设置clear:both而不是before来更加优雅的清除浮动。

总结:

通过clear属性清除浮动:

设置clear:left的元素会清除写在该元素代码前面设置float:left元素的浮动效果

设置clear:right的元素会清除写在该元素代码前面设置float:right元素的浮动效果

设置clear:both的元素会清除写在该元素代码前面设置float的元素的浮动效果(不管你左浮动右浮动)

所以我们都会在浮动元素代码最后位置放上一个元素带有属性clear:both。

添加元素清除浮动

    <div class="contain">
        <div style="float:left">浮动</div>
        <div style="float:left">浮动</div>
        ......
        <div style="clear:both"></div>
    </div>

或者添加伪元素清除浮动

 <style>
        .contain::after{
            content: '';
            display: block;
            clear: both;
        }
 <style>
    <div class="contain">
        <div style="float:left">浮动</div>
        <div style="float:left">浮动</div>
        ......
    </div>

方法一的最后还要提醒一下:

添加元素的时候一定要用块级元素

使用伪元素的时候一定要设置display:block(不设置默认行内元素)

为什么?因为clear属性只针对块级元素生效。

方法二,设置overflow:hidden(实际上是生产BFC父级元素达成清除浮动效果)

 <style>
    .contain {
      background-color: orange;
      overflow: hidden;
    }
    .float {
      width: 100px;
      height: 100px;
      margin: 0 10px;
      float: left;
      background-color: blue;
    }
  </style>
 <div class="contain">
    <div class="float"></div>
    <div class="float"></div>
  </div>

效果图

进入主题之前先介绍一波BFC(Block Formatting Context): 块(Block)格式化(Formatting)上下文(Context): 规定内部块级元素布局方式。

  • BFC布局规则
    • 内部的块级元素会在垂直方向,一个接一个地放置;
    • 块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并;
    • 每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
    • BFC的区域不会与float box重叠;
    • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;
    • 计算BFC的高度时,浮动元素也参与计算

BFC相关引用自文章:为什么"overflow:hidden"能清除浮动的影响

且看最后一条:“计算BFC的高度时,浮动元素也参与计算”,这意味着我们只要创建一个BFC的父元素,那么内部就算有浮动元素,它的高度也会计算进去。所以只要我们能够把父元素变成BFC,这样我们就能够实现清除浮动了!

  • 那么如何生成BFC呢?首先我们要知道怎样创建BFC。一个BFC可以被显式触发,只需满足以下条件之一:

    • float的值不为none;
    • overflow的值不为visible;
    • position的值为fixed / absolute;
    • display的值为table-cell / table-caption / inline-block / flex / inline-flex。

BFC相关引用自文章:为什么"overflow:hidden"能清除浮动的影响

至此,我们应该明白为什么浮动元素的父元素加上overflow:hidden就可以清除浮动,其实不止hidden,auto,其他满足上面生成BFC条件都可以做到清除浮动(上述BFC介绍以及生成仅引用其他文章,具体BFC详情有兴趣可以自行查阅)

总结:

使用overflow:hidden方式实际就是生成一个BFC,BFC内部计算高度会算上内部浮动元素高度,从而达到清除浮动目的。(你当然也可以对父元素使用oveflow:auto或者float:left这样...,总之这些都是利用BFC来达到清除浮动目的)

写在结尾:

以上就是两种清除浮动的原理讲解,添加clear属性你可以通过新增标签与生成伪元素的方式清除,生成BFC你可以通过各式各样的生成BFC来清除浮动,只要样式是你需要的,个人比较推荐伪元素方法,也是各路文章比较推荐的。

ps:这是本人第一次写关于技术文章,虽然不是什么很难的点,网上大家也都能搜到,但是希望还是能帮到大家,可能有些啰嗦,哈哈哈,如果文章中有什么错误或者不严谨的地方欢迎指正交流,同进步。

2757