CSS Float是网页设计最强大的灵活性功能之一。本文介绍CSS Float的基本原理和行为特征,并介绍各种浏器Float特性的Bugs。
内容
- 基本的浮动原理
- 浮动是如何进行的
- 浮动从何处开始
- 水平浮动堆叠
- 反向浮动
- Clearing Floats
基本的浮动原理
任何元素 element 都可以被浮动。段落、div、list、tables,以及图像都可以被浮动,事实上即使是像 span 和 strong 这样的行内置元素也可以很好地进行浮动。
任何申明为 float 的元素自动被设置为一个"块级元素", 这表示它可以具有申明的"width"和"height"属性。事实上,floats当前被要求具有一个申明的宽度,但这不是现代浏览器制造者的思 路,W3C以及开始同意这样的作法。现在大多数人的意见是没有指定宽度的float应当伸缩包装到浮动内容的宽度。因此,内部带有图片的一个float将 和图片一样宽,带有文本的一个浮动将与该浮动内的最长文本行一样宽。
CSS2.1的浮动规则中这样讲: "如果 width 是以 auto 方式计算得到,使用的值是 shrink-tofit 伸缩到适合的宽度。" 所有现代的浏览器已经这样做,除了IE5/Mac。除非浮动具有某种指定的宽度,否则该浏览器会变得错误百出。现在大多数聪明的编码人员会让浏览器伸缩其 没有宽度属性的floats, 并使用一个隐藏的专门给IE5/Mac的宽度知识。这可能不算很巧妙,但是它是现在不能满足该规范的极少数的浏览器,同时Mac用户有几种更好的选择。 MS停止了对IE5/Mac的支持,因此寻求像伸缩包装式浮动这样有用特性被避免的代价太高了,这样只有IE5/Mac用户不会看到错误的浮动。
浮动是如何进行的
浮动"从流程中被移除出来", 但是与绝对位置的元素(层次)不同,浮动是在他们前面的最后一个块元素之后直接被显示出来(就像块盒一样)。如果该浮动是在一个“行块”中,该浮动的上边 界被放置在行块顶部的水平上。当除此以外,浮动与绝对元素相似,原先的块盒会完全忽略浮动和AP元素。那些静态的块盒知识保持一个接一个地”跟随“,就好 像没有浮动不在那里一样。
The following is minimal code for the example graphic:
上例展示了行盒在一个浮动中是如何被削短的。你可以让行内元素(像文本、图像)在一个浮动的边上放置并且在它的下面继续,就好像使用很好的老式(不过已过时)图像的属性"align=left"。浮动,比这要灵活的多。
认为跟在一个浮动后面的块元素会被设置为放置在浮动的下方是通常的一个误解。事实上,只有在哪些块元素内部的”行盒“才会这样。
还记得我提到的浮动被从文档处理流程中移除出来的话吗?标准要求在一个浮动后面的行盒被进行足够的削短以保持行盒在外部开放区。这表示文本和行内的 图像永远不会被浮动覆盖,除非他们其中之一或两个在独立的、指定位置的容器中。这就是说,如果一个浮动被嵌套在一个绝对位置的元素中,并且AP元素被设置 为覆盖一个段落,在段落中的行盒不会被浮动削短,这是因为他们不同的上下文环境造成的。而且,文本的确会被该浮动覆盖。
对于浮动的一个常见错误是:将文本保留在该浮动的边界之外。对浮动后面跟着的段落放置padding或设置边界是不会生效的,因为这些属性被应用在 跟随在浮动后面的段落的左边。正确的方式是对浮动本身设置margins,这样可以让行盒正确显示,浮动要比它呈现的要更大,并且对他们进行相应的削短。 大多数浮动通常只是从按照最靠近文本的边和底部获得这样的边界信息。上面浮动的截图有一个小的右边界。
同时跟在float后面的块盒只是被该浮动覆盖(即使他们的内容已经被移动到边上)。如果该浮动被设置的非常高,它可以挡住大量堆叠的块盒上,就像第二个截图看到的那样:
该图展示了浮动是如何覆盖多个块盒的。
如上所示,浮动的另一个行为是他们的”方向”。当一个浮动被定义的时候,总是被给予一个方向值。(“left”或“right”),例如:div{ float:left;}. 这些值简单地将浮动移到到容器盒的指定边界。
偶尔,float的新手会试图使用浮动值,例如{float:up;} or {float:botton;}, 但是这些值是无效的,在浮动的标准中并没有计划要添加这些值。人们总是可以期待...
浮动从何处开始
如果一个浮动在两个块盒之间,它会将其上边界放置在前置块盒的下边界上,并且将其移动到左(或右边),直到达到外界容器元素的边界,通常是<body>元素。
如果浮动被嵌套在第二个块盒中,并且该容器盒没有边框盒填充,浮动呈现样式,与浮动被放置在块盒之间是一样的。但是,如果这些块盒通过边距分离,该 浮动的顶部边界从一个盒与另一个盒边界的交叉点上开始。在以下截图中,块盒右顶部边界,但是左侧的浮动的左边距已经被移动以显示缺省的动作。:
<p>Paragraph</p> <!-- first block box (complete) --> <div style="float:left; width:30%;"> <p>Left float text</p></div> <div> <!-- second block box --> <div style="float:right; width:150px;"> <p>Right float text</p> </div> <p>Text following the right nested float</p> </div>
该图展示了浮动可能被放置在不同的位置。
水平浮动堆叠
如果居左的浮动被放置在其容器的左上脚,并且其后跟随一个同向的浮动,该浮动会被放置在容器右上脚,然后移动到左侧,边界延伸到第一个浮动的右侧时停止。
最后的一种行为让我们创建整行的floats,每个都被放置在前一个的右侧(或者左侧,如果使用{float:right;}). 同样,当一行中没有足够的空间时,多出来的floats绕到下一行,非常像行内元素那样。这对于制作可点击的图像“简略图”非常方便,因为矩阵会自动调整 到屏幕的尺寸,只是简单地在需要时进行回绕。
以下是一行彩色的左向浮动。左上方的浮动在源代码中先出现,右下方的最后。他们都有一个小的边距以便看起来更好一些。试一下将浏览器的尺寸变小一些,观察浮动行被回绕以使用窗口尺寸。
Float 1 Float 2 Float 3 Float 4 Float 5 Float 6 Float 7 Float 8 Float 9 Float 10 Float 11 Float 12 Float 13 Float 14 Float 15
上述浮动会回绕以使用任何屏幕的尺寸。注意其下段落(不可见)的文本同样也调整以使用浮动排列的变化。该段落实际上从第一个浮动开始的地方开始,但是只有在段落文本可见的情况下,该事实才不明显。截图中的段落具有边框盒背景以便显示实际的位置。
如果浮动被设置为“右侧”而不是“左侧”,其行为完全相同,知识浮动从右开始,而不是从左开始,后续的浮动被添加到左侧行尾而不是右侧。两种情况,回绕都是一样的,除非float的Bugs导致差异。
用这样的方式思考,一个容器中的浮动首先被移到它能够到达的最上方的空间(在其定位的方向),然后按设置的浮动反向移动直到到达容器的边界,或者遇 到另一个浮动。每个连续的浮动都是同样处理,直到其中一个浮动在另一个浮动的level中无法发现足够宽的空间。这样,它会被强制停止到另一个浮动的底 部,然后向之前那样进行滑行。
Float 1 Float 2 Float 3 Float 4 Float 5 Float 6 Float 7 Float 8 Float 9 Float 10 Float 11 Float 12 Float 13 Float 14 Float 15 Float 16 Float 17 Float 18 Float 19 Float 20
警告!注意上面的浮动的高度不是一样的。当一个浮动被放置到第二行紧接第一行时,它视图滑行到边界,当遇到第一高的浮动时会被停住。当有大量不规则浮动时,这会造成很丑陋的情况。上面的浮动中包含一些比其他高一些的浮动。
缩小你的浏览器以不同的屏幕宽度来测试。
在追着一个大型的简略图矩阵时,必须注意确保所有的浮动具有同样的高度,或者页面可以轻易地被出轨的浮动重新组装。
本文中的所有例子都使用了特殊的处理以适应IE5.x/win盒模式的缺点。由于边框和填充造成了必须特殊处理。
反向浮动
Clearing Floats
以下开始讲述关于浮动的最晦涩、最难以理解的部分。
回顾一下跟随浮动后面的静态盒。这些盒只是忽略浮动,并且在前一个静态盒的后面排列显示。假设你给以下盒一个清除属性, {clear:both;}。这是将被清除盒的顶部边距扩展,将其向下推直到清理浮动的底部。换句话说,该被清理的盒的顶部边距(无论它之前被设置成什么 值),都会被浏览器增加到需要保证被清理盒位于浮动下回的长度。
这样的效果是,一个被清理的盒无法与前置浮动保持在同一个水平位置上。它必须出现在其下方。以下图例展示了效果。
展示一个盒如何清理下方的一个浮动。
记住,浮动实际上并不是真正地被包含在一个块盒中,即使在源代码中是怎样嵌套的。请注意确认,浮动的屏幕开始点是由它所嵌套的位置决定的,之后它只是在容器盒上展开,就像绝对元素一项。只有包含行内元素的行盒(例如文本),才需要关注浮动在哪里被显示。
制作一个看起来封装一个嵌套浮动的外容器的标准方法是在容器的最后放置一个完整“被清理”的元素:
<div> <!-- float container --> <div style="float:left; width:30%;"><p>Some content</p></div> <p>Text not inside the float</p> <div style="clear:both;"></div> </div>
由于div没有被浮动,容器必须识别它并封装它,并且由于顶部边距(由于“clear”属性由浏览器添加),该div将容器的底部边界拉到浮动框的底部。
的确,这是一个古怪的方法,但是标准就是这样说的。不过,W3C中有一个讨论关于添加一个容器自动封装一个浮动的规则。这样就于更加简单。
事实上,IE盒Opera7已经自动封装嵌套的浮动,与标准不一样。Opera6不是这样,因此看来Opera在跟随MS的非标准道路。
还可以使用 {clear:left;} 或 {clear:right;}. 这可以让一个元素清除左侧浮动当不影响右侧浮动,或者相反。要使用这种控制你需要有相当的想像力。
通常来说,清除可以很好地完成,但是有时会引起不大不小的错误,这完全是由IE造成的。