CSS学习(4)浮动

18 阅读9分钟

前言

  • 清除浮动的方法有哪些?

浮动出现的背景

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

<div id="text1">A</div>
<div id="text2">
  怒发冲冠,凭栏处、潇潇雨歇。抬望眼、仰天长啸,壮怀激烈。三十功名尘与土,八千里路云和月。莫等闲、白了少年头,空悲切。靖康耻,犹未雪。臣子恨,何时灭。驾长车,踏破贺兰山缺。壮志饥餐胡虏肉,笑谈渴饮匈奴血。待从头、收拾旧山河,朝天阙。
</div>
#text1 {
    float: left;
    width: 100px;
    height: 100px;
    border: 2px solid red;
}
#text2 {
    width: 400px;
    height: 400px;
    border: 2px dashed green;
}

效果查看

screenshot-20240708-161518.png

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

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

浮动实现布局

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

两列布局

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

<div id="text1">
  <h2>《破阵子·为陈同甫赋壮词以寄之》</h2>
  醉里挑灯看剑,梦回吹角连营。八百里分麾下炙,五十弦翻塞外声,沙场秋点兵。马作的卢飞快,弓如霹雳弦惊。了却君王天下事,赢得生前身后名。可怜白发生!
</div>
<div id="text2">
  <h2>《满江红》</h2>
  怒发冲冠,凭栏处、潇潇雨歇。抬望眼、仰天长啸,壮怀激烈。三十功名尘与土,八千里路云和月。莫等闲、白了少年头,空悲切。靖康耻,犹未雪。臣子恨,何时灭。驾长车,踏破贺兰山缺。壮志饥餐胡虏肉,笑谈渴饮匈奴血。待从头、收拾旧山河,朝天阙。
</div>
  body {
    width: 90%;
    margin: 0 auto;
  }
  #text1 {
    float: left;
    width: 48%;
  }
  #text2 {
    float: right;
    width: 48%;
  }

效果查看

image.png

三列布局

<div id="text1">
  <h2>《破阵子·为陈同甫赋壮词以寄之》</h2>
  醉里挑灯看剑,梦回吹角连营。八百里分麾下炙,五十弦翻塞外声,沙场秋点兵。马作的卢飞快,弓如霹雳弦惊。了却君王天下事,赢得生前身后名。可怜白发生!
</div>
<div id="text2">
  <h2>《满江红》</h2>
  怒发冲冠,凭栏处、潇潇雨歇。抬望眼、仰天长啸,壮怀激烈。三十功名尘与土,八千里路云和月。莫等闲、白了少年头,空悲切。靖康耻,犹未雪。臣子恨,何时灭。驾长车,踏破贺兰山缺。壮志饥餐胡虏肉,笑谈渴饮匈奴血。待从头、收拾旧山河,朝天阙。
</div>
<div id="text3">
  <h2>《水调歌头》</h2>
  明月几时有?把酒问青天。不知天上宫阙,今夕是何年。我欲乘风归去,又恐琼楼玉宇,高处不胜寒。起舞弄清影,何似在人间。转朱阁,低绮户,照无眠。不应有恨,何事长向别时圆?人有悲欢离合,月有阴晴圆缺,此事古难全。但愿人长久,千里共婵娟。
</div>
  body {
    width: 90%;
    margin: 0 auto;
  }
  #text1 {
    float: left;
    width: 30%;
  }
  #text2 {
    float: left;
    width: 30%;
  }
  #text3 {
    float: right;
    width: 30%;
  }

效果查看

screenshot-20240708-163334.png

浮动的特性

1. 脱离标准流

参考以下例子:由于红色的div浮动脱离了标准流,所以蓝色的div就往上走了。

<div id="text1"></div>
<div id="text2"></div>
  #text1 {
    width: 100px;
    height: 100px;
    background-color: red;
    float: left;
  }
  #text2 {
    width: 200px;
    height: 200px;
    background-color: blue;
  }

效果查看

screenshot-20240708-164116.png

2. 浮动的元素互相贴靠

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

  #text2 {
    width: 200px;
    height: 200px;
    background-color: blue;
    float: left;
  }

还是刚才的例子,我们让蓝色的div也浮动,效果如下:

screenshot-20240708-164525.png

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

  #text2 {
    width: 2000px;
    height: 200px;
    background-color: blue;
    float: left;
  }

20240708-164822.gif

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

3. 宽度收缩

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

20240708-165450.gif

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

清除浮动

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

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul>
  <li>菜单1</li>
  <li>菜单2</li>
  <li>菜单3</li>
</ul>
  li {
    width: 100px;
    height: 50px;
    background-color: #ccc;
    float: left;
  }

效果查看

screenshot-20240708-170222.png

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

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

1. 给父元素设置高度

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

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

ul {
  height: 50px;
}

20240708-170825.gif

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

20240708-171053.gif

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

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

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

2. clear 属性

在实际开发中,由于盒子的高度能够被内容撑开,所以很多时候我们不会设置高度。这时候就可以使用css中的clear属性。

css中clear属性定义了元素的哪一侧不允许出现浮动元素。

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

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

描述
left在左侧不允许浮动元素。
right在右侧不允许浮动元素。
both在左右两侧均不允许浮动元素。
none默认值。允许浮动元素出现在两侧。
inherit规定应该从父元素继承 clear 属性的值。

下面我们使用clear来清除浮动:

ul:nth-of-type(2) {
    clear: both;
    margin-top: 50px;
  }

效果查看:

screenshot-20240708-172225.png

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

例如我们添加一个margin-top,会发现该margin没有生效。

3. 隔墙法

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

例如:

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<div class="clearfix"></div>
<ul>
  <li>菜单1</li>
  <li>菜单2</li>
  <li>菜单3</li>
</ul>
  ul:nth-of-type(2) {
    /* clear: both; */
    margin-top: 50px;
  }
  .clearfix {
    clear: both;
  }
  li {
    width: 100px;
    height: 50px;
    background-color: #ccc;
    float: left;
  }

效果查看:

screenshot-20240708-172815.png

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

4. 内墙法

通过隔墙法,后面又衍生出了内墙法。内墙法就是将"墙"写在父元素的里面。

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
  <div class="clearfix"></div>
</ul>

<ul>
  <li>菜单1</li>
  <li>菜单2</li>
  <li>菜单3</li>
</ul>

5. overflow 属性

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

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

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>

<ul>
  <li>菜单1</li>
  <li>菜单2</li>
  <li>菜单3</li>
</ul>
  ul {
    overflow: hidden;
  }
  ul:nth-of-type(2) {
    margin-top: 50px;
  }
  li {
    width: 100px;
    height: 50px;
    background-color: #ccc;
    float: left;
  }

screenshot-20240708-175306.png

6. 伪类清除法

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

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

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>

<ul>
  <li>菜单1</li>
  <li>菜单2</li>
  <li>菜单3</li>
</ul>
  ul:nth-of-type(1)::after {
    content: '';
    display: block;
    clear: both;
    height: 0;
    visibility: hidden;
  }
  ul:nth-of-type(2) {
    margin-top: 50px;
  }
  li {
    width: 100px;
    height: 50px;
    background-color: #ccc;
    float: left;
  }

screenshot-20240708-175306.png

浮动的现状

上面介绍了很多清除浮动的方法,这些其实都是时代的眼泪,最初的css设计不是特别严谨,没有考虑到这些问题。

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

浮动目前仅仅也就在要制作文字环绕效果时,能发挥一席之地。然而,文字环绕这种90年代看着还不错的设计,现在又有几几个设计师会这样设计网页呢?

总结

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

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

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

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

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