float详解

使得元素脱离文档流有两种方式。第一种是通过定位,第二种方法就是使用浮动。
浮动(float),是一个我们即爱又恨的属性。爱,因为通过浮动,我们能很方便地布局;恨,因为浮动之后遗留下来太多的问题需要解决,特别是 IE6-7(以下无特殊说明均指 windows 平台的 IE 浏览器)。如果不详细了解浮动,可能会觉得它很神秘也很复杂,很多网站的效果好看,但是自己就是做不出来。
很多初学者都会有这样的疑问:浮动从何而来?为什么要设置浮动?我们为何要清除浮动?清除浮动的原理是什么?
现在我们就深入剖析float的奥秘,解开这些问题的答案。

一、什么是浮动?浮动最常见的问题是什么?

最简单的解释,浮动可以使得多个块级元素可以放置在同一行上。例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>z-index</title>
</head>
<body>
  <div class="main left">
    .main:我是主要内容
  </div>
  <div class="side left">
    .side:我是侧边栏
  </div>
</body>
</html>

.main {
    height: 60px;
    width: 50%;
    background: #FFE3D7;
}
.left {
    float: left;
}
div {
    padding: 15px 20px;
    font-size: 14px;
    color: #333;
}
.side {
    width: 20%;
    background: lightblue;
}

在这里插入图片描述
这种浮动有什么用?其实很多网站的两栏或者三栏结构都是利用浮动来实现的。例如:
在这里插入图片描述
然而浮动初学者经常出现的问题是,浮动元素脱离的文档流,因此,它无法使得其他元素和其相对位置关系保持正常。也无法使得自己的父容器正确计算自己的大小。对于上面的例子,如果我们使得 main 元素和 side 元素有一个父容器 wrap,并且父容器还有一个兄弟节点 footer:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>z-index</title>
</head>
<body>
    <div class="warp">
        <div class="main left">
            .main:我是主要内容
        </div>
        <div class="side left">
            .side:我是侧边栏
        </div>
    </div>
    <div class="footer">
        我是一个footer
    </div>
</body>
</html>

.main {
    height: 60px;
    width: 50%;
    background: #FFE3D7;
}
.left {
    float: left;
}
div {
    padding: 15px 20px;
    font-size: 14px;
    color: #333;
}
.side {
    width: 20%;
    background: lightblue;
}
.warp {
    border: 1px solid blue;
    width: 300px;
    margin: 30px auto 5px;
    background: #F5F5F5;
}
.footer {
    border: 1px solid #ccc;
    background: #EEE;
    width: 300px;
    margin: 5px auto 30px;
}

在这里插入图片描述
可以看到两个最大的问题:

  • wrap 元素的高度无法正确覆盖住 main 和 side 元素。
  • 由于 wrap 元素高度计算的问题,footer 元素本身显示的位置非常奇怪。通常解决浮动元素带来的问题有两种主要方式:清除浮动和闭合浮动。那么:
二、该 清除浮动 还是 闭合浮动?

很多人都已经习惯称之为清除浮动,以前我也一直这么叫着,但是确切地来说是不准确的。我们应该用严谨的态度来对待代码,也能更好地帮助我们理解上面的问题。
1)清除浮动:清除对应的单词是 clear,对应 CSS 中的属性是 clear:left | right | both | none;
2)闭合浮动:更确切的含义是使浮动元素闭合,从而减少浮动带来的影响。
两者的区别:

两者的区别:

清除浮动:

<div class="warp">
        <div class="main left">
            .main:很抱歉,现代浏览器中我没能把warp撑高(float:left)
        </div>
        <div class="side left">
            .side:我也浮动了(float:left)
        </div>
    </div>
    <div class="footer clear">
        .footer:我通过设置clear:both <strong>清除浮动</strong>,虽然位置正确了,但是wrap的高度没变,还是没达到想要的效果
    </div>

.clear {
    clear: both;
}

在这里插入图片描述

<div class="warp clearfix">
        <div class="main left">
            .main:warp自己闭合浮动了,所以footer不用再清除浮动了(float:left)
        </div>
        <div class="side left">
            .side:我也浮动了(float:left)
        </div>
    </div>
    <div class="footer clear">
        .footer:warp通过 .clearfix 已经<strong>闭合浮动</strong></div>

.clearfix:after {
    clear: both;
    content: ".";
    display: block;
    height: 0;
    visibility: hidden;
}
.clearfix {
    *zoom: 1;
}

在这里插入图片描述
通过以上实例发现,其实我们想要达到的效果更确切地说是闭合浮动,而不是单纯的清除浮动,在 footer 上设置 clear:both 清除浮动并不能解决 wrap 高度塌陷的问题。
结论:用闭合浮动比清除浮动更加严谨,所以后文中统一称之为:闭合浮动。

三、为何要闭合浮动?

要解答这个问题,我们得先说说 CSS 中的定位机制:普通流,浮动,绝对定位(其中"position:fixed" 是 “position:absolute” 的一个子类)。

1)普通流:很多人或者文章称之为文档流或者普通文档流,其实标准里根本就没有这个词。如果把文档流直译为英文就是 document flow,但标准里只有另一个词,叫做普通流(normal flow),或者称之为常规流。但似乎大家更习惯文档流的称呼,因为很多中文翻译的书就是这么来的。比如《CSS Mastery》,英文原书中至始至终都只有普通流 normal flow(普通流)这一词,从来没出现过 document flow(文档流)

2)浮动:浮动的框可以左右移动,直至它的外边缘遇到包含框或者另一个浮动框的边缘。浮动框不属于文档中的普通流,当一个元素浮动之后,不会影响到块级框的布局而只会影响内联框(通常是文本)的排列,文档中的普通流就会表现得和浮动框不存在一样,当浮动框高度超出包含框的时候,也就会出现包含框不会自动伸高来闭合浮动元素(“高度塌陷”现象)。顾名思义,就是漂浮于普通流之上,像浮云一样,但是只能左右浮动。

正是因为浮动的这种特性,导致本属于普通流中的元素浮动之后,包含框内部由于不存在其他普通流元素了,也就表现出高度为 0(高度塌陷)。在实际布局中,往往这并不是我们所希望的,所以需要闭合浮动元素,使其包含框表现出正常的高度。

四、该如何正确闭合浮动呢?

先看一下闭合浮动的各种方法:

1)添加额外标签

一种方法,通过在浮动元素末尾添加一个空的标签例如

,其他标签 br 等亦可。例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>z-index</title>
</head>
<body>
    <div class="warp">
        <div class="main left">
            .main:我是主要内容
        </div>
        <div class="side left">
            .side:我是侧边栏
        </div>
        <div class="clear"></div>
    </div>
    <div class="footer">
        我是一个footer
    </div>
</body>

在这里插入图片描述
优点:通俗易懂,容易掌握
缺点:可以想象通过此方法,会添加多少无意义的空标签,有违结构与表现的分离的思想,在后期维护中将是噩梦,这是坚决不能忍受的,所以我们不推荐使用该方法。

2)使用 br 标签和其自身的 html 属性

这个方法有些小众,br 有 clear=“all | left | right | none” 属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>z-index</title>
</head>
<body>
    <div class="warp">
        <div class="main left">
            .main:我是主要内容
        </div>
        <div class="side left">
            .side:我是侧边栏
        </div>
        <br clear="all">
    </div>
    <div class="footer">
        我是一个footer
    </div>
</body>
</html>

优点:比空标签方式语义稍强,代码量较少
缺点:同样有违结构与表现的分离,不推荐使用

3)父元素设置 overflow:hidden

通过设置父元素 overflow 值设置为 hidden;在 IE6 中还需要触发 hasLayout,例如 zoom:1;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>z-index</title>
</head>
<body>
    <div class="warp close">
        <div class="main left">
            .main:我是主要内容
        </div>
        <div class="side left">
            .side:我是侧边栏
        </div>
    </div>
    <div class="footer">
        我是一个footer
    </div>
</body>
</html>

.close {
  overflow: hidden;
  *zoom: 1;
}

优点:不存在结构和语义化问题,代码量极少
缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素;所以也不推荐使用。

4)父元素设置 overflow:auto 属性

同样 IE6 需要触发 hasLayout,演示和 3 差不多
优点:不存在结构和语义化问题,代码量极少
缺点:多个嵌套后,Firefox 某些情况会造成内容全选;IE 中 mouseover 造成宽度改变时会出现最外层模块有滚动条等,Firefox 早期版本会无故产生 focus等。

5)父元素也设置浮动

优点:不存在结构和语义化问题,代码量极少
缺点:使得与父元素相邻的元素的布局会受到影响,不可能一直浮动到 body,不推荐使用。

6)父元素设置 display:table
.close {
  display: table;
}

优点:结构语义化完全正确,代码量极少。
缺点:盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用。

7)使用:after伪元素

需要注意的是:after 是伪元素(Pseudo-Element),不是伪类(某些 CSS 手册里面称之为“伪对象”),很多闭合浮动大全之类的文章都称之为伪类,不过要严谨一点,这是一种态度。
由于 IE6-7 不支持:after,使用 zoom:1 触发 hasLayout。
优点:结构和语义化完全正确,代码量中等
缺点:复用方式不当会造成代码量增加

小结:

通过对比,我们不难发现,其实以上列举的方法,无非有两类:
其一,通过在浮动元素的末尾添加一个空元素,设置 clear:both 属性,after 伪元素其实也是通过 content 在元素的后面生成了内容为一个点的块级元素;
其二,通过设置父元素 overflow 或者 display:table 属性来闭合浮动,我们来探讨一下这里面的原理。

作者:灯火葳蕤234
链接:https://www.jianshu.com/p/2c1708a73438
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值