共计 5952 个字符,预计需要花费 15 分钟才能阅读完成。
前言
提到浮动,前端的小伙伴必定都不生疏,然而随着弹性布局等等一些更好用的规范进去后,用在布局方面少了很多,当初我刚开始接触前端的时候,很习惯用浮动来给元素扭转定位,过后还并不是很风行 flexbox 布局,很多布局会通过浮动来实现,然而应用浮动来布局会产生一些副作用,比方尽管应用浮动能够使元素向左或向右靠齐,但会造成高度坍塌,过后的我并不太理解其中的原因,只是机械地从网上搜寻到一些解决高度坍塌的代码,到当初也不能算是理解的很透彻,只能算是比刚开始做前端的时候多理解了一点。
脱离文档流
在说到浮动的时候,很多中央都会说,它们脱离了文档流,那么失常状况下文档流是怎么样的呢?
写过 HTML 的小伙伴应该都理解,HTML 中的元素利用的是默认的流式布局;假如页面上有一个 div
,而后还有一个span
,如果咱们不编写额定的款式扭转它们的布局形式,它们会依照默认的规定布局,div
是块状元素,默认占满行,即便给 div 设置了宽度,也是占着一行,如果有多个 div 会纵向一个个排布,而 span
是行内元素,通常行内元素会搁置在块容器外部,如果有多个 span 会默认横向从左向右一个挨一个排布。
利用了浮动的元素就不受流式布局的管制了。比方利用了 float: left;
的div
,它不再会占满一整行,利用了 float: right;
的span
,能够从右向左排布。
那么浮动有什么特点,革除浮动又是什么意思呢?
浮动
前端有几个较为有名的布局形式,比方圣杯布局、双飞翼布局等等,应用 float
是实现这些布局的形式之一,当然当初咱们能够应用更便捷的形式来实现,比方 flex 弹性布局、grid 网格布局等等,在这方面浮动的利用应该少了很多,但其实浮动它本来设计之初应该就不是为了这些布局(个人观点,暂未考据),这从它的名称上就能够窥见。
咱们能够把文档设想成一个水面,而浮动元素就好比是浮在水面上的船。水波盘绕船体,就像浮动元素被其余内容盘绕一样。比方上面这张图:
设计 float
属性次要就是实现这种成果,这从标准文档中的形容就能看出:
The most interesting characteristic of a float (or “floated” or “floating” box) is that content may flow along its side (or be prohibited from doing so by the ‘clear’ property). Content flows down the right side of a left-floated box and down the left side of a right-floated box.
浮动框(或 “ 浮动 “ 或 “ 浮动 “ 框)最乏味的特点是,内容能够沿其侧面流动(或通过 “ 革除 “ 属性禁止流动)。内容能够沿着左浮动框的右侧流动,也能够沿着右浮动框的左侧流动。
这里流动的内容就能够比作流动的水,所以咱们常常能看到应用 float
实现文字盘绕成果的例子。比方标准文档中给出的例子:
只能说早些时候的 CSS 还不够欠缺,不能满足一些非凡的布局需要,而 float
恰好误打误撞能够满足,这算是一种 css hack 吧。
当应用 float:left;
或者 float: right;
申明某个节点后,这个节点就变成了水面上的船,一个本身分量为 0 的船,齐全浮在水面上,当船上没有任何货色时,它不会影响到水面,而当咱们往其中减少内容之后,船就会向水面下沉一点,从而影响到水面。产生相似于标准文档中的以下形容:
Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist. However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.
因为浮动框不在流中,在浮点框之前和之后创立的非定位块框会垂直流动,就像浮动框不存在一样。不过,在浮动框旁边创立的以后和后续行方框会依据须要缩短,以便为浮动框的 margin box 留出空间。
float 会影响所在行的行方框,也就是line boxes
。就相似于影响到水面的面积。
革除浮动
在应用浮动用于布局之后,咱们经常须要革除浮动,那么革除浮动是什么意思呢?这里能够持续用后面浮在水面上的船来举例子,尽管可能不算很贴切。
船在水面上是浮动着的,随着水流的作用会飘移,那么就有可能飘移到其余的水域,革除浮动就相似于阻止这艘船飘移,比方装置一道闸门,避免船飘进来或飘进来。通过设置特定的 css 属性来革除浮动,就相似于这里的装置闸门。
创立 BFC 容器
之前在《对 BFC 的了解》中咱们有提到过,能够通过创立 BFC 容器的形式来革除浮动,比方设置display: flow-root;
,这就相似于在一个水域的上游处装置闸门,避免这个水域内的船飘往上游。
假如有以下一段 HTML:
<div style="width: 100px; height: 100px; border: 1px solid orange; float: left;">
<span> 文本文本 111 文本文本 111 文本文本 111</span>
</div>
<div style="width: 100px; height: 100px; background: pink;">
<span> 文本文本 222</span>
</div>
在未革除浮动前是这样的:
能够看到,文本 111
占用了 文本 222
所在 div 的容器,就像是船飘到了上游的水域,占了 文本 222
的地位。
将第一个 div 用 BFC 容器包裹后(相似于闸门的作用):
<div style="display: flow-root;">
<div style="width: 100px; height: 100px; border: 1px solid orange; float: left;">
<span> 文本文本 111 文本文本 111 文本文本 111</span>
</div>
</div>
<div style="width: 100px; height: 100px; background: pink;">
<span> 文本文本 222</span>
</div>
页面就变成了上面这个样子:
应用 clear 属性
能够看到在标准文档中,还间接提供了一个 clear
属性用于革除浮动。
This property indicates which sides of an element’s box(es) may not be adjacent to an earlier floating box. The ‘clear’ property does not consider floats inside the element itself or in other block formatting contexts.
该属性示意元素方框的哪些边不得与先前的浮动方框相邻。” 革除 ” 属性不思考元素自身外部或其余块格局上下文中的浮动。
创立 BFC 的形式能够类比为上游水域在上游口装置了闸门,应用 clear
属性就能够类比为上游水域在上游口装置闸门,避免上游的船飘进来。所以后面的例子中,咱们也能够应用以下代码来革除浮动:
<div style="width: 100px; height: 100px; border: 1px solid orange; float: left;">
<span> 文本文本 111 文本文本 111 文本文本 111</span>
</div>
<div style="width: 100px; height: 100px; background: pink; clear: left;">
<span> 文本文本 222</span>
</div>
能够看到,最终成果和下面创立 BFC 的成果是一样的。但理论我之前看到的解决浮动的计划中,比拟举荐的做法是由浮动的元素这边来解决革除,比方创立 BFC 容器,或者加在伪元素 before
或者 after
上。比方上面这段代码:
<div id="float-box">
<div style="width: 100px; height: 100px; border: 1px solid orange; float: left;">
<span> 文本文本 111 文本文本 111 文本文本 111</span>
</div>
</div>
<style>
#float-box::after {
content: '';
display: block;
clear: left;
}
</style>
<div style="width: 100px; height: 100px; background: pink;">
<span> 文本文本 222</span>
</div>
下面的代码中应用 ::after
元素创立了一个看不见的块来革除浮动。
clear
属性能够设置多种值。
Name: | clear |
---|---|
Value: | none/left/right/both/inherit |
Initial: | none |
Applies to: | block-level elements |
Inherited: | no |
Percentages: | N/A |
Media: | visual |
Computed value: | as specified |
依据文档里的形容,left
值示意以后块不被相邻的左浮动框影响,right
值示意以后块不被相邻的右浮动框影响,both
示意同时不受两类浮动框的影响。
然而标准文档中也提醒咱们,应用 clear
属性会产生副作用,应用 none
以外的值可能会引入间隙(clearance)。
Values other than ‘none’ potentially introduce clearance. Clearance inhibits margin collapsing and acts as spacing above the margin-top of an element. It is used to push the element vertically past the float.
“none”以外的值可能会引入间隙。间隙会克制边距折叠,并充当元素顶部边距上方的间距。它用于将元素垂直推过浮动。
在《对 BFC 的了解》中,咱们提到过,在 BFC 容器中,相邻块级盒子之间的垂直 ’margin’ 会折叠。这里的意思应该就是指,设置了 clear
属性为非 none
之后,会影响 BFC 容器里的垂直 margin
折叠。
文档中给出了间隙的值是怎么计算得出的:
Then the amount of clearance is set to the greater of:
- The amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.
- The amount necessary to place the top border edge of the block at its hypothetical position.
而后将间隙量设置为以下两者中的较大值:
1. 将块的边界边缘与要革除的最低浮动的底部外边缘对齐所需的量。
2. 将块的顶部边框边缘搁置在其假如地位所需的量。
光从形容上看,有点形象,尤其是第二种计算,这里所谓的假如地位是哪里呢?第一种仿佛好了解一些,就是让两个边缘对齐的一个距离的量。所以文档中也举了例子来配合讲解。
- 示例 1
从名称就能够看出,F 是个浮动块高度为 H,此时 B1 有个 bottom margin 值为 M1,B2 有个 top margin 值为 M2,在 B2 未设置 clear 属性之前,B1 和 B2 之间的间距为 M1 和 M2 中的较大值,也就是产生了垂直 margin
的折叠。
假如 B1 的底部边框在 y = 0 这个地位,就如上图所示,此时浮动框 F 的顶部地位就在 y =M1 的地位,而 B2 的顶部边框就在 y =max(M1,M2)的地位,浮动框 F 的底部地位在 y =M1+ H 的地位。
在这个例子中,B2 不在 F 上面,这个例子所形容的就是须要增加间隙的场景。也就是说:
max(M1,M2) < M1 + H
依据文档中形容的计算形式,这里须要计算两次间隙量,C1 和 C2,而后取两者中的较大值:C = max(C1, C2)
。
第一种办法是使 B2 的顶部与 F 的底部齐平,即 y(top of B2) = M1 + H。这意味着 margin 不再折叠(B1 和 B2 的间距必定大于 M1 和 M2),它们之间有了间隙:
此时它们的等式关系为:
F 的底部 = B2 的顶部边框
M1 + H = M1 + C1 + M2
C1 = M1 + H - M1 - M2
= H - M2
第二中计算是放弃 B2 的顶部地位,即 y(top of B2) = max(M1,M2)。也就是 B2 边框在其假如地位,依照预期放弃垂直 margin
折叠的成果。此时的等式关系就是编程上面这样了:
max(M1, M2) = M1 + C2 + M2
C2 = max(M1, M2) - M1 - M2
因为假如了max(M1,M2) < M1 + H
,因而能够得出以下不等式:
C2 = max(M1, M2) - M1 - M2 < M1 + H - M1 - M2 = H - M2
C2 < H1 - M2
又因为C1 = H1 - M2
,所以在这个场景中C2 < C1
。因而间隙量 C =max(C1, C2)=C1。
- 示例 2,负值间隙
<p style="margin-bottom: 4em">
First paragraph.</p>
<p style="float: left; height: 2em; margin: 0">
Floating paragraph.</p>
<p style="clear: left; margin-top: 3em">
Last paragraph.</p>
在最初一个 p
元素未设置 clear
属性之前,第一个和最初一个 p
元素之间的 margin
会折叠,最初一个 p
元素的顶部边框边缘(top border edge)会与浮动 p
元素的顶部齐平。
当咱们设置 clear
属性用于革除浮动时,须要让最初一个 p
元素的 top border edge 位于浮动框的上面,也就是说须要往下移动 2em
。此时必须引入间隙,相应地,margin
不再折叠,此时咱们来计算间隙量:
c + m-t = 2em
c = 2em - m-t = 2em - 3em = -1em
第一种形式计算 C1 = H – M2 = 2em – 3em = -1em
第二种计算形式,也就是放弃 最初一个 P
元素 的顶部地位,C2 = max(M1, M2) – M1 – M2 = 4em – 4em – 3em = -3em
所以最初 C =max(C1,C2)=-1em。
从下面两个例子能够看出,间隙量的两种计算形式的区别就在于,是否扭转浮动框后续元素的顶部地位。
总结
随着弹性布局、网格布局等一系列新的布局形式引入后,浮动的应用少了很多,但它依然能实现非凡的网页成果,因而咱们还是须要对它进行必要的理解。