(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
(注2:更多内容请查看我的目录。)
1. 简介
在当前行中一个盒被移动到左侧或右侧称为浮动。浮动最有趣的特点是内容可以在其侧面流动(或者被 clear 属性禁止这样做)。内容沿着左浮动框的右侧向下流动,并沿右浮动框的左侧向下流动。下面我们来看一下 浮动定位 和 内容流。
2.浮动对布局的影响
浮动盒将向左或向右移动,直到其外边缘接触包含块边缘或另一个浮动的外边缘。如果存在行盒,浮动盒的外部顶部outer top将与当前行盒的顶部对齐。
如果水平方向没有足够的空间容纳浮动,它将下移直至能够放下它或者没有其他浮动存在。
由于浮动不在标准流中,在浮动之前或之后创建的非定位块盒将垂直摆放,如同浮动不存在一样。然而,如果当前行盒和随浮动后创建的行盒与浮动相邻,会按需缩短来为浮动的margin box腾出空间。
当一个垂直定位满足以下全部四个条件时,行盒将与浮动相邻:
- 在行盒顶部或之下
- 在行盒底部或之上
- 在浮动的top margin edge 之下,
- 在浮动bottom margin edge之上
注:这意味着总高度 Outer Height 为零或为负的浮动不会缩短行盒。
如果行盒被缩短到不能容纳任何内容,那么行盒将下移(其宽度会重新计算)直到可以容纳内容或不再有浮动。当前行中,任何在浮动盒之前的内容将重排到同一行中的浮动的另一侧。换句话说,如果行内级盒先于左浮动被放在行盒中,而行盒的剩余空间可以容纳左浮动,那么左浮动会被置于该行内,且与行盒顶部对齐,而已经放入该行盒的行内级盒会被相应地移动到浮动的右侧(右侧即是左浮动的另一侧),反过来对 rtl 和右浮动也是这样。
表的border box、块级可替换元素或者在标准流中创建了新的BFC的元素(比如 overflow 值非 visibile 的元素),它们不能与其同属一个BFC中的浮动元素的margin box重叠。如果有必要,应当通过把它们置于已出现的浮动的下面达到清除浮动的效果,但如果空间足够,可能将其紧邻浮动放置,但这可能使得该元素的border变得比section 10.3.3定义的要窄。CSS2并没有定义用户代理何时会把元素置于浮动旁,也没有定义元素会变得多窄。
看一个例子,在下面的文档片段中,包含块太窄不足以容纳紧邻浮动的内容,所以这块内容需要移动到浮动下面,并根据其 text-align 属性在行盒中对齐。
p {
width: 10em;
border: solid aqua;
}
span {
float: left;
width: 5em;
height: 5em;
border: solid blue;
}
...
<p>
<span> </span>
Supercalifragilisticexpialidocious
</p>
该片段可能如下图所示:
若干浮动会相邻,而这个模型也适用于同一行中的相邻的浮动元素。
看下例,下面的规则会使所有的 class="icon" 的 img 盒浮动到左侧(并设置左外边距为 0 )。
img.icon {
float: left;
margin-left: 0;
}
考虑如下HTML代码和样式表:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Float example</title>
<style type="text/css">
img { float: left }
body, p, img { margin: 2em }
</style>
</head>
<body>
<p><img src=img.png alt="This image will illustrate floats">
Some sample text that has no other...
</body>
</html>
img 盒向左浮动。其后的内容被格式化到浮动的右侧,从浮动所在的同一行开始布局。由于浮动的存在,浮动右侧的行盒缩短,但在浮动之后就恢复了它们“正常”宽度(即 p 元素创建的包含块的宽度)。该文档可能被格式化如下:
如果文档如下,格式化的结果是一样的:
<body>
<p>Some sample text
<img src=img.png alt="This image will illustrate floats">
that has no other...
</body>
这是因为浮动左侧的内容为浮动所替代,并被向下重排到了浮动的右侧。
正如8.3.1节
所述,浮动元素的margins绝对不会与相邻盒的margins折叠。因此,在之前的例子中, p 盒和 img 浮动盒的垂直外边距不会折叠。
浮动的内容会像浮动创建了新的堆叠上下文 Stacking Context 一样堆叠起来,但定位元素、创建了新的堆叠上下文并参与了浮动的父级堆叠上下文的元素除外。浮动可以同常规流中的其他盒重叠(例如,当浮动旁边的常规流盒有负margin的时候)。当发生重叠时,浮动会被渲染在非定位文档流内块 Non-positioned In-flow Blocks 之上,文档流内行内盒之下。
这有个例子,演示了浮动与常规流中元素的边框重叠的情况。
浮动图片挡住了与其重叠的块盒的边框。
下面的例子演示了使用 clear 属性阻止内容紧邻浮动。
假设规则如下:
p { clear: left }
格式化结果可能如下所示:
两个段落都设置了 clear: left ,因此使得第二个段落“被往下推”到浮动之下的位置,这是“空隙clearance”被添加到其top margin 之上的结果。
3. 浮动定位:float属性
这个属性指定一个盒子是应该向左浮动,向右浮动还是不浮动。它可以被任何元素设置,但仅适用于生成非绝对定位盒的元素。该属性值具有如下含义:
- left
该元素生成一个浮动到左侧的块盒。内容在盒的右侧从顶部向下流动(受clear属性限制) - right
该元素生成一个浮动到右侧的块盒。内容在盒的左侧从顶部向下流动(受clear属性限制) - none
该盒不浮动
用户代理会视根元素上的 float 为 none 。
以下是控制浮动行为的准则:
左浮动盒的左外边缘不可在其包含块的左边缘之左。右浮动元素亦是。
如果当前盒是左浮动,而此前源文档中已有元素生成了左浮动盒,那么对每个此前生成的盒而言,要么当前盒的左外边缘在此前生成盒的右外边缘之右,要么当前盒的顶部必须低于此前生成盒的底部。右浮动元素亦是。
左浮动盒的右外边缘不可在其旁边的右浮动盒的左外边缘之右。右浮动元素亦是。
浮动盒的上外边缘不可高于其包含块的顶部。当浮动出现两个折叠外边距之间时,浮动会如同它有一个参与标准流的空匿名父块一样来定位。该父块的位置由关于外边距折叠那章的规则定义。
浮动盒的上外边缘不可高于源文档中此前元素生成的块盒或浮动盒的上外边缘。
元素的浮动盒的上外边缘不可高于源文档中此前元素生成的盒所在的行盒的顶部。
一个左浮动盒如果有其他左浮动盒在其左侧,其右外边缘不可在其包含块的右边缘之右。(宽松点的要求是:左浮动不可超出其包含块的右边缘,除非该盒已经尽可能靠左了。)右浮动元素亦是。
浮动盒必须尽可能地往高摆放。
-
左浮动盒的摆放必须尽可能地靠左,右浮动盒必须尽可能靠右。更高的位置优先于更靠近左/右的位置。
但是在CSS2.2中,如果,在BFC中,有一个文档流内负垂直高度的外边距,使得浮动的位置高于它原本应当在的位置,所有这种负外边距被设为零,浮动的位置则未定义。
这些规则中提到的其他元素仅指:和浮动同属一个BFC的其他元素。
这个HTML片段结果为 b 向右浮动
<p>a<span style="float: right">b</span></p>
如果 p 元素足够宽, a 和 b 则会各占一边,如下所示:
4. 控制浮动旁的流: clear 属性
该属性指定元素的哪些侧边不允许同此前的浮动盒相邻。 clear 属性不考虑其元素本身内的浮动或者处于其他BFC的浮动。
各值被应用于非浮动块级盒时,具有如下意义:
left:要求盒的top border edge低于源文档内此前元素生成的左浮动盒的bottom outer edge。
right:要求盒的top border edge低于源文档内此前元素生成的右浮动盒的bottom outer edge。
both:要求盒的top border edge低于源文档内此前元素生成的左、右浮动盒的bottom outer edge。
none:对盒相对于浮动的定位没有约束。
clear 取非 none 值可能产生空隙 Clearance 。空隙阻止外边距折叠并充当元素上外边距margin-top之上的空间。空隙被用于推动元素在垂直方向上越过浮动。
计算设置了 clear 值的元素的空隙,首先要计算元素top border edge的假定位置,该位置即元素 clear 属性值为 none 时实际top border edge应该在的位置。
如果元素上边框边缘的假定位置没有越过有关浮动,那么空隙就会产生,并且外边距折叠要根据8.3.1章规则计算。
空隙的高度被设为下述中的较大值:
块的边框边缘border edge与要被清除的最下方的浮动的下外边缘bottom outer edge不相交的必要高度。
将块的上边框边缘top border edge放在其假定位置的必要高度。
二选一的话,空隙高度即第一种。
注:两种方式在目前的网页内容的兼容性上有待评估。未来的CSS规范将规定为其中一个或另一个。
注:空隙可以为负或为零。
来看两个例子:
eg1:假设(为简单起见)有三个盒,顺序如下: B1 块的下外边距bottom margin为 M1 ( B1 没有子元素也没有padding和border);浮动块 F 的高度为 H , B2 块top margin为 M2 (没有padding或border,没有子元素)。 B2 的 clear 设为 both 。同时假设 B2 不为空。
不考虑 B2 的 clear 属性,情况如下图所示。 B1 和 B2 的外边距margins折叠。 B1 的bottom border edge在 y = 0 的位置, F 的top在 y = M1 的位置, B2 的top border edge在 y = max(M1,M2) 的位置, F 的bottom在 y = M1+H 的位置。
同时假设 B2 不在 F 之下,也就是说,正如规范说明的情况,我们需要添加空隙。
max(M1,M2) < M1 + H
我们需要计算空隙 C两次,即C1 和 C2 ,并取二者较大值: C = max(C1,C2) 。第一种方法是把 B2 的顶部top和 F 的底部bottom齐平,即,放在 y= M1+H 。也意味着外边距之间的空隙使得外边距不再折叠:
bottom of F = top border edge of B2 ⇔
M1 + H = M1 + C1 + M2 ⇔
C1 = M1 + H - M1 - M2
= H - M2
第二次计算是保持 B2 顶部位置,即 y=max(M1,M2) 处,这意味着:
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 < H - M2
又因为 C1 = H - M2,得
C2 < C1
因此
C = max(C1,C2) = C1
eg2: 本例中空隙的高度为负值-1em。(假设所有元素都没有边框或borders者内边距padding)
<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>
说明:要是没有 clear ,首段和末段两个段落的边距将会折叠并且末段的上边框边缘将同浮动段落的顶部齐平。如下:
但 clear 使得上边框边缘低于浮动,即下降2em。这意味着一定会产生空隙。
由此,外边距不再折叠,空隙的高度 clearance 满足
clearance + margin-top = 2em
也就是说,
clearance = 2em - margin-top = 2em - 3em = -1em
当 clear 设在浮动元素上时,将造成第3节所述浮动定位规则的修正。补充第10条额外规定如下:
(当 clear 设在浮动元素上时,)浮动的上外边缘top outer edge必须低于所有此前左浮动盒的下外边缘bottom outer edge( clear: left 情形下),或者低于所有此前的右浮动盒的下外边缘( clear: right 情形下),或者低于此前左右浮动盒的下外边缘( clear: both 情形下)。
注意:CSS1中该属性适用于所有元素,因此所有元素都能实现效果。在CSS2和CSS2.2中, clear 属性仅支持块级元素。因此开发者们应当只将此属性应用于块级元素。如果要实现行内元素清除浮动效果,不应当如上所讲的去设置空隙,而应当强制断行并有效插入一个或多个空行盒(或者如section 9.5所讲移动新行盒)来使要清除浮动的行内元素的行盒低于相应的浮动盒。
参考
https://www.w3.org/TR/CSS22/visuren.html#visual-model-intro
https://www.w3.org/TR/CSS2/visuren.html
CSS规范 > 9 视觉格式化模型 Visual Formatting Model