1 前言
在CSS中,有3种常用的方法可以对元素进行定位、布局:
normal flow
:标准流absolute positioning
:绝对定位float
:浮动
绝对定位、浮动都会让元素脱离标准流、以达到灵活布局的效果。
2 设置浮动
通过float
属性可能让元素产生浮动效果,float
的常用取值有:
none
:不浮动(默认值)left
:元素向左侧浮动right
:元素向右侧浮动
对元素设置float
将会触发BFC
(块状格式化上下文)
3 浮动的规则
元素一旦浮动,就会脱离标准流,它会朝着向左或向右的方向移动,直到自己的边界紧贴着包含块(一般是父元素)或者遇到其他浮动元素的边界为止。
规则一:脱离标准流
我们通过以下的例子来演示一下:
1 |
|
浮动前
由于我们将所有div
都设置为了行内块级元素,所以它们可以行内元素span
共处一行,并且由于3号浮动元素尚未开启浮动,4号定位元素是相对定位,使得它们二者还处在标准流中,将会根据元素的先后位置进行排列。
因此,这四个元素呈现的效果如下所示:
浮动后
开启右浮动
那么,如果我们给3号浮动元素开启浮动呢?比如,我们给它设置float: right
,让它向右侧进行浮动。3号右侧没有其他的浮动元素,因此,它会一直运动到父元素的右侧边界处。同时,由于3号元素浮动,脱离标准流,不再占据原有的位置,那么4号定位元素将会向前移动。
因此,这四个元素呈现的效果如下所示:
开启左浮动
那么,我们如果给3号元素设置左浮动,让它向左侧进行浮动呢?先来看一下最终呈现的效果,如下图所示:
由于我们对3号元素设置了float: left
,元素将会向左侧方向移动,因为左侧没有其他浮动元素,因此,它将一直移动到父元素的左侧边界为止。其他元素按照原有的排列顺序向后移动。
❓❓❓这里提一个小问题:
如果在4号定位元素后面新增一个5号静态元素,那么5号元素将会在哪呢?
来看一下下面的演示:
由于5号静态元素也属于行内块级元素,所以它将会被排列到4号定位元素的后面。并且,如果当减小浏览器的宽度时,由于一行的宽度已经容不下5号元素了,所以它将会排列到下一行。
规则二:元素之间的层叠关系
浮动元素会层叠在普通块级元素上,定位元素还会继续层叠在浮动元素上方
有如下基本结构:
1 |
|
此时,浮动元素还没有开启浮动,定位元素也没有设置定位值,四个元素的排列顺序如下:
浮动元素覆盖普通元素
先为3号浮动元素开启浮动,设置float: left
。由于它脱离标准流,将不再占据原有的位置,因此4号静态元素将会向上移动。
页面效果如下:
4号静态元素去哪了呢?它被浮动元素覆盖掉了,我们只要为4号静态元素设置一些外边距margin-top: 50px; margin-left: 50px;
,让它移动一下,就可以看到它了。
如果你明白了浮动元素会层叠在普通元素上方后,就可以接着往下看了❤❤❤
定位元素覆盖浮动元素
在3号浮动元素上方还有一个定位元素,我们为它设置一下定位值top: 50px; left: -100px
,来看一下页面效果:
可以看到,2号定位元素又覆盖在3号浮动元素上方。
❓❓❓这里再提一个小问题:(怎么又有问题了?)
==“4号静态元素”==这几个字为什么跑到父元素的边缘位置了呢?不是设置了text-align: center
吗?
带着这个问题,我们将来到浮动元素的第三个规则部分
规则三:浮动元素挤占行内元素
浮动元素会覆盖普通的块级元素,那么浮动元素和行内元素相遇呢?
会挤占行内元素的位置!
挤占行内兄弟元素
有如下基本结构:
1 |
|
此时,浮动元素还没有开启浮动,页面效果如下:
如果我们为其开启浮动float: left
,它会脱离文档流,向左侧浮动。它左侧没有其他浮动元素,因此,它将一直移动到父元素的左侧外界为止。
在浮动元素上方还有一个行内元素,浮动元素会覆盖掉这个行内元素吗?并不会,它会把行内元素挤到一边去。
挤占块级元素中的行内元素
有如下基本结构:
1 |
|
页面效果如下:
如上图所示,浮动元素除了会挤占与自己同处一行的行内兄弟元素外,它也是会挤占其他元素中的行内元素的。
为了充分理解,我做了以下几个动态图来演示:
一开始我们先让2号静态元素的行高恢复成默认状态,然后来调节1号浮动元素的大小,看一下浮动元素是如何挤占2号静态元素的中文字内容的
当没有设置行高时,行高由文字内容决定。当浮动元素的宽度不断增大时,将会把2号静态元素中的文字内容挤到下一行。
然后,我们给2号静态元素设置行高,让文本内容处于居中状态。再来看一下
这里也是如此,浮动元素会把文字内容挤占到下一行,但是由于设置的有行高,因此挤占到下一行时,文字的位置有所变化。
除了div
是块级元素,p
也是一个非常常见的块级元素。而p
元素中的内容也属于行内元素,它如果和浮动元素同处一行,也是会挤占这些文字的。但是,如果p
元素中的文字内容过少,我们一般只能发现文字被挤占到一边了。但如果我们减小父元素的宽度,增加p
元素中的内容,就可以发现有图文环绕效果。
有如下基本结构:
1 |
|
页面效果如下:
规则四:浮动元素不会超出包含块
其实这个问题在规则二中就已经可以看到了。我们把之前的图片拿来再看一次
如上图所示:我们给父元素设置了边框,浮动元素发生浮动后,最多就是到达父元素的边界为止,不会再继续移动。但是,定位元素就不那么听话了!可以看到,它已经跑到父元素外边了。
4 浮动带来的问题
父元素高度塌陷
在上面的案例上,你是否注意到了所有的父元素都指定了高度呢?
接下来要说的,就是浮动与父元素高度之间的问题了。在开发中,我们一般不会把父元素的高度写死,而是让父元素的高度是由子元素的内容的高度撑起来。
有如下基本结构:
1 |
|
页面效果如下:
上面的代码中,并没有指定父元素的高度,它完全由内容撑开。
一旦对两个元素设置了浮动,那么它们将会脱离标准流,即已经不再处于父元素所在的文档流中,那么父元素中就可以视作没有元素,因此父元素的高度将会塌陷。如下图所示:
可以看到,父元素的高度变成了4px
,这4px
是由上下2px
的外边框形成。其实说父元素的高度变为0px
,应该明确指出是父元素的内容高度height
为0px
,而非实际高度。实际高度还包括border
和padding
,这两个属性的值仍然可以让父元素有高度。
浮动元素本身的高度和宽度
不指定父元素的高度和宽度时,一旦子元素浮动,父元素就会发生高度塌陷问题。那么子元素如果不设置高度和宽度呢?
我们知道宽度的默认值是auto
,它会充分利用可利用的空间,这句话的意思是如果没有指定父元素的padding
,没有指定子元素的margin
,子元素的宽度就是父元素的宽度。
有如下基本结构:
1 |
|
页面效果如下:
当我们给1号浮动元素设置float: left
,它的宽度将变成刚好够包裹着元素内容本身。
如果再去除1号浮动元素的宽度,则这个元素就变得如同行内元素一般。如下所示:
5 清除浮动
清除浮动有多种方法,其原理都是通过clear
属性来实现。这个属性用于清除浮动,规定元素的哪一侧不允许存在其他浮动元素。
我们常说的清除浮动不是指将浮动元素清除掉,而是指将浮动元素对其他元素造成的影响清除掉。
clear
属性的常用取值有:
left
:元素左侧不允许有浮动元素right
:元素右侧不允许有浮动元素both
:元素左侧和元素右侧都不允许有浮动元素
方法一:为兄弟元素设置clear
样式
1 |
|
此时,2号浮动元素还没有开启浮动。页面效果如下:
如果此时,为2号浮动元素开启浮动float: left
,2号元素将会脱离文档流,向左侧浮动,但是由于1号静态元素是块级元素,2号浮动元素最多只能浮动到它的下方。随着2号浮动元素的脱标,3号静态元素将会向上移动。最终效果如下:
那么如何清除浮动元素造成的影响呢?
因为浮动元素脱标,造成下一个元素上移,后面如果还有其他元素都会跟着移动。因此,我们只要能保证浮动元素后的下一个元素位置恢复正常,其他的布局将都会恢复正常。
只需要给3号静态元素设置clear: left
,规定3号静态元素左侧不允许存在浮动元素,就可以让3号静态元素恢复正常布局。当然,你也可以直接写成clear: both
,这样,不论2号元素设置左侧浮动,还是右侧浮动,都能奏效。
如上图所示,3号静态元素回到正常位置。
方法二:空标签清除浮动
还是那句知,浮动元素脱标会导致它后面的元素的位置发生变化。因此,只要能够保证紧跟这个浮动元素后的一个元素可以清除掉这种影响,就可以恢复正常布局。
第二种方法,我们不针对浮动元素后现有的元素进行设置clear: both
属性,而是在浮动元素后面添加一个空div
标签,对它进行设置clear: both
属性。
DOM核心结构如下:
1 | <div class="wrap"> |
CSS核心样式如下:
1 | .clear { |
这种方法有其缺点:会增加许多无意义的空标签,且结构与表现未分离,因此并不推荐使用。
方法三:br标签清除浮动
br
标签清除浮动的方法类似空标签清除浮动,在浮动元素后面添加一个br
标签,在br
标签中设置属性clear
,并赋值all
,即<br clear='all'>
1 | <div class="wrap"> |
方法四:创建BFC
为父元素设置overflow: hidden
或者overflow: auto
,可以使父元素形成BFC,所谓形成BFC,就是指这个元素内部无论发生什么变化,都不会影响到外面的布局。
因此,可以利用这一点来清除浮动。
例如:当3号静态元素浮动后,就可以通过给父元素设置over: hidden
来清除浮动。
1 |
|
当3号元素浮动后,由于2号元素(这里没有开启浮动)是块级元素,3号元素不可以超过2号元素,因此,将处于它的下方,移向左侧位置。页面效果如下:
此时我们为父元素添加overflow: hidden
,再来看一下效果:
浮动造成的影响已经清除掉了,父元素的高度是正确的高度。
如果我们先去除父元素的overflow: hidden
,再为2号元素也开启浮动,页面效果将如下所示:
然后我们重新给父元素设置overflow: hidden
,来看一下效果:
可以看到,父元素的高度也恢复了正常。
那么,我们又一次去除父元素的overflow: hidden
,并且给1号元素也开启浮动,页面效果将如下所示:
父元素的高度已经完全塌陷,3个子元素依照顺序先后浮动。
重新给父元素设置overflow: hidden
,来看一下效果:
父元素的高度也恢复正常了。
那么,如果我们单独为2号元素设置浮动(为了显示3号元素,为其添加了margin-left
)呢?页面效果如下所示:
因此2号元素浮动了,所以造成3号静态元素上移了。那么我们给父元素设置overflow: hidden
会让3号元素下移到原来的位置吗?
答案是不会!
即使你设置了overflow: hidden
,3号元素也不会下移。那为何给3号元素设置浮动时,overflow: hidden
就会使父元素的高度恢复正常呢?
那是因为现在的高度就是正常的高度。2号元素浮动以后,3号静态元素将会上移,和2号元素处于同一行。父元素的高度已经把3号静态元素的高度包括在内了。
这里把之前给3号元素开启浮动的页面效果拿来做一下对比,就清楚了。
单独为3号元素开启浮动时,通过边框线就可以知道,父元素的高度没有将3号元素的高度包括进去。
单独为2号元素开启浮动时,通过边框给就可以知道,父元素的高度已经将3号元素的高度包括进去了。所以,这个时候再设置overflow: hidden
,其实所实现的效果并非让3号元素下移,不要混淆。
方法五:伪元素(推荐)
为当前浮动元素的父元素添加after
伪元素,为after
伪元素设置清除浮动的代码即可。
1 | <!DOCTYPE html> |
我们为2号元素、3号元素开启了浮动,父元素的高度没有将二者包括进行。页面效果如下所示:
我们通过给父元素添加clearfix
类,通过clearfix::after
伪元素就可以给父元素添加一个最后的子元素。然后再通过clearfix::after
来设置这个子元素的clear
样式等。其实和在浮动元素后面添加一个空标签类似,只不过这种方法不会在页面中添加许多无意义的元素。
添加clearfix
类后,页面效果如下:
本文作者: CoderLeiShuo
本文链接:https://coderleishuo.github.io/lele/719.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!