Skip to content

浮动

经典真题

  • 清除浮动的方法
  • 以下选项能够清除浮动的是( )

A. 空 div

B. hover 伪选择器

C. clear 属性

D. overflow 属性

关于浮动,你需要知道的东西

浮动出现的背景

浮动属性产生之初是为了实现“文字环绕”的效果,让文字环绕图片,从而使网页实现类似 word 中“图文混排”的效果。来看下面的例子:

<div class="container">
  <img src="./ok.png" alt="" width="200">
  <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Doloribus quos est rerum repellat alias maiores
    nobis harum recusandae corrupti assumenda qui aut ipsam deserunt dolorem modi, culpa hic ex illo repellendus
    atque. Numquam iste porro perspiciatis. Harum esse magni exercitationem, perspiciatis libero soluta quo ea
    dolorem. Delectus tempore magnam vitae voluptatibus, non quasi laudantium, aliquam consequuntur perspiciatis
    maiores esse neque animi voluptate. Animi pariatur debitis quam aliquam recusandae quis ut nisi totam sint
    consectetur distinctio, quos saepe cum quo iure natus delectus! Ad, dolore. Ut temporibus ea autem fugiat
    laboriosam quidem iste rerum laborum. Repellendus recusandae sequi id excepturi alias?</p>
</div>
.container {
  width: 800px;
  border: 1px solid;
}

效果如下:

image-20210918111724895

由于 p 段落是块级元素,所以独占一行,图片和段落是分开的。

接下来我们设置图片浮动:

.container {
  width: 800px;
  border: 1px solid;
}
img{
  float: left;
}

效果如下:

image-20210918112006064

当我们设置了图片浮动后,就出现了类似 “word” 的文字环绕效果。

这实际上也是浮动最初被设计出来的目的。

浮动实现布局

到了后面,浮动渐渐被应用到了页面布局上。因为 HTML 里面的元素,要么是行内元素,要么是块级元素,这种方式是没办法做页面布局的,例如我想实现两个块级元素在一行。此时开发人员就想到了浮动,因为任何东西都可以浮动,而不仅仅是图像,所以浮动的使用范围扩大了,能够用来进行布局。

两列布局

下面我们来看一下使用浮动实现的两列布局:

<h1>2 column layout example</h1>
<div>
  <h2>First column</h2>
  <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem
    placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet
    nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
    tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada
    et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
    sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius
    commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
</div>

<div>
  <h2>Second column</h2>
  <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est,
    posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam
    lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis
    finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in
    interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
body {
  width: 90%;
  max-width: 900px;
  margin: 0 auto;
}

div:nth-of-type(1) {
  width: 48%;
  float: left;
}

div:nth-of-type(2) {
  width: 48%;
  float: right;
}

效果:

image-20210918130208288

在上面的代码中,我们让两个 div 一个左浮动一个右浮动,从而实现了两列布局的效果。

三列布局

现在我们已经有了一个两列布局工作,添加一个第三列(或更多)并不是太难。

下面是一个使用浮动实现的三列布局。

<h1>3 column layout example</h1>
<div>
  <h2>First column</h2>
  <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem
    placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet
    nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
    tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada
    et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
    sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius
    commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
</div>

<div>
  <h2>Second column</h2>
  <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est,
    posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam
    lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis
    finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in
    interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
<div>
  <h2>Third column</h2>
  <p>Nam consequat scelerisque mattis. Duis pulvinar dapibus magna, eget congue purus mollis sit amet. Sed euismod
    lacus sit amet ex tempus, a semper felis ultrices. Maecenas a efficitur metus. Nullam tempus pharetra
    pharetra. Morbi in leo mauris. Nullam gravida ligula eros, lacinia sagittis lorem fermentum ut. Praesent
    dapibus eros vel mi pretium, nec convallis nibh blandit. Sed scelerisque justo ac ligula mollis laoreet. In
    mattis, risus et porta scelerisque, augue neque hendrerit orci, sit amet imperdiet risus neque vitae lectus.
    In tempus lectus a quam posuere vestibulum. Duis quis finibus mi. Nullam commodo mi in enim maximus
    fermentum. Mauris finibus at lorem vel sollicitudin.</p>
</div>
body {
  width: 90%;
  max-width: 900px;
  margin: 0 auto;
}

div:nth-of-type(1) {
  width: 36%;
  float: left;
}

div:nth-of-type(2) {
  width: 30%;
  float: left;
  margin-left: 4%;
}

div:nth-of-type(3) {
  width: 26%;
  float: right;
}

效果:

image-20210918130610163

浮动的特性

在上面,我们已经实现了两列布局和三列布局,可以看出,浮动确实能够拿来布局。

接下来我们就需要具体研究一下浮动有哪些特性了。

  1. 脱离标准流

浮动的第一个特点就是脱离标准流,例如:

<div class="one"></div>
<div class="two"></div>
.one {
  width: 80px;
  height: 80px;
  background-color: red;
  float: left;
}

.two {
  width: 150px;
  height: 150px;
  background-color: blue;
}

效果如下:

image-20210918131127272

由于红色的 div 浮动脱离了标准流,所以蓝色的 div 自然而然就往上走了。

  1. 浮动的元素互相贴靠

如果有多个浮动的元素,那么会相互贴靠,如果宽度不够,会重启一行。

.two {
  width: 150px;
  height: 150px;
  background-color: blue;
  float: left;
}

还是上面的 DOM 结构,我们让 two 这个盒子也浮动,效果如下:

image-20210918131424633

如果宽度不足以让后面的盒子贴靠,那么后面浮动的元素会被排列到下一行:

.two {
  width: 850px;
  height: 150px;
  background-color: blue;
  float: left;
}

效果:

image-20210918131627324

在上面的示例中,我们将蓝色盒子的宽度修改为了 850px,当我们缩小浏览器时,由于宽度不够蓝色盒子重新排列到了第二排。

  1. 宽度收缩

在没有设置宽度的情况下,块级元素在标准流时很多时独占一行,宽度也会占满整个容器,但是一旦被设置为浮动后,宽度就会收缩。

例如:

<div>this is a test</div>
div{
  background-color: red;
  float: left;
}

本来 div 是占满整行的,但是当我们设置了浮动后,由于 div 又没有设置宽度,所以宽度就收缩了。

清除浮动

有些时候,浮动会带来副作用,所以我们需要清除浮动带来的副作用。

例如:

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul>
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

效果:

image-20210918132700157

在上面的示例中,我们本来是打算做两个导航栏的,但是由于浮动的贴靠性质,导致所有的 li 都在一行了。

这个时候我们就需要一些方式来清除浮动。

  1. 给父元素设置高度

在上面的示例中,由于 li 的父元素 ul 没有高度,所以导致明明不是同一个父元素下的浮动子元素,也会相互贴靠。

此时我们就给 li 的父元素 ul 设置一个高度即可。例如:

ul{
  height: 50px;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

效果:

image-20210918133638708

需要注意给父元素设置高度时,这个高度值一定要大于浮动子元素的高度,这样才能关注浮动。例如:

ul{
  height: 30px;
}
li {
  float: left;
  width: 100px;
  height: 70px;
  background-color: pink;
}

效果:

image-20210918133928678

在上面的示例中,虽然我们给父元素 ul 设置了高度,但是这个高度值是小于浮动元素 li 的高度的,此时我们会发现仍然有贴靠的现象。

因此,如果一个元素要浮动,那么它的祖先元素一定要有高度。有高度的盒子,才能关住浮动

只要浮动在一个有高度的盒子中,那么这个浮动就不会影响后面的浮动元素。所以就是清除浮动带来的影响了。

  1. clear 属性

在实际开发中,由于盒子的高度能够被内容撑开,所以很多时候我们不会设置高度。

那么这个时候又该如何清除浮动呢?

CSS 中有一个叫做 clear 的属性,该属性定义了元素的哪边上不允许出现浮动元素。

CSS1CSS2 中,这是通过自动为清除元素(即设置了 clear 属性的元素)增加上外边距实现的。

CSS2.1 中,会在元素上外边距之上增加清除空间,而外边距本身并不改变。不论哪一种改变,最终结果都一样,如果声明为左边或右边清除,会使元素的上外边框边界刚好在该边上浮动元素的下外边距边界之下。

clear 属性的取值如下:

image-20210918141612213

接下来我们来用 clear 属性清除浮动:

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two{
  clear: left;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

效果:

image-20210918143310665

可以看到,浮动的副作用确实是清除了,但是这种方式有一个问题,那就是 margin 属性失效了。

例如我们在 two 的样式里面添加一个 margin-top,会发现该 margin 属性的设置并不起效果。

  1. 隔墙法

隔墙法的核心思想就是在两个浮动的元素之间添加一个空的 div 作为一堵“墙”,从而让后面的浮动元素,不去追前面的浮动元素。

例如:

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<div class="clearfix"></div>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}

.clearfix {
  clear: both;
}

li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

效果:

image-20210918144154274

通过上面的示例我们可以看到,margin 已经恢复正常。

  1. 内墙法

通过隔墙法,后面又衍生出了内墙法。内墙法的出现,可以让浮动的元素也能撑开父元素的高。

正常情况下,没有高的父元素,里面的子元素一旦浮动,高度也就没有了,例如:

<div>
  <p></p>
</div>
div{
  background-color: green;
}
p{
  width: 100px;
  height: 100px;
  background-color: red;
}

当前效果:

image-20210918145912989

一旦我们设置 p 元素为浮动,由于脱离了标准流,所以父元素的高也就消失了。

此时就可以使用内墙法来给父元素撑起高,如下:

<div>
  <p></p>
  <div class="clearfix"></div>
</div>
div{
  background-color: green;
}
p{
  width: 100px;
  height: 100px;
  background-color: red;
  float: left;
}
.clearfix{
  clear: both;
}

效果:

image-20210918150838625

下面是使用内墙法清除浮动的示例:

<div>
  <ul>
    <li>导航1</li>
    <li>导航2</li>
    <li>导航3</li>
  </ul>
  <div class="clearfix"></div>
</div>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}

.clearfix {
  clear: both;
}

li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

效果如下:

image-20210918151358700

在上面的代码中,我们使用内墙法清除了浮动,并且父元素的高度也被撑起来了,margin 也是正常的。

  1. overflow 属性

overflow 属性本来是用作处理溢出内容的显示方式的。

当给父元素添加 overflow:hidden 之后,父元素就会形成一个 BFC,一块独立的显示区域,不受外界影响,所以通过这种方式也能够去除浮动的副作用。

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}

ul {
  overflow: hidden;
}

li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

在上面的代码中,我们设置两个父元素 ul 都为 overflow:hidden 之后,两个父元素形成了 BFC,我们可以看到父元素的高度也被撑开了,margin 也是正常的。

  1. 伪类清除法

最后要介绍的,是目前最流行的浮动清除方式,伪类清除法。

该方法的核心思想就是为父元素设置一个伪元素,其实就是无形的添加了一堵墙,然后在伪元素中设置一系列的属性。例如:

<ul class="one">
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}

.one::after {
  content: "";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

在上面的代码中,我们为第一个 ul 设置了 after 伪元素,并在伪元素中设置了诸如 clear:both、visibility: hidden 等一系列属性,这实际上就等同于在两个 ul 之间添加了一堵无形的墙。

浮动的现状

上面介绍了很多清除浮动的方法,一会儿外墙法、一会儿内墙法、一会儿 overflow,这些其实都是时代的眼泪。

目前来讲,除非要考虑古老的 IE6/IE7,否则布局压根儿就不会考虑浮动,有更好的弹性盒模型和网格布局供我们使用。

浮动目前仅仅也就在要制作文字环绕效果时,能发挥一席之地的作用。

然而,文字环绕这种 90 年代看着还不错的设计,现在又有几个设计师会这样设计网页呢?

真题解答

  • 清除浮动的方法

参考答案:

  • clear 清除浮动(添加空 div 法)在浮动元素下方添加空 div,并给该元素写 css 样式 {clear:both;height:0;overflow:hidden;}

  • 给浮动元素父级设置高度

  • 父级同时浮动(需要给父级同级元素添加浮动)

  • 父级设置成 inline-block,其 margin: 0 auto 居中方式失效

  • 给父级添加 overflow:hidden 清除浮动方法

  • 万能清除法 after 伪类清浮动(现在主流方法,推荐使用)

  • 以下选项能够清除浮动的是( B )

A. 空 div

B. hover 伪选择器

C. clear 属性

D. overflow 属性

-EOF-