浮动模型(Float Model)是完全不同于流动模型的另一种布局模型,它遵循浮动规则,但是仍然受流动模型带来的潜在影响。任何元素在默认状态下是不浮动的,但都可以通过 CSS 定义为浮动于左右的属性(float: left; 或 float: right;)时定义为浮动。浮动模型汲取了流动模型和层模型的优点,以尽可能实现网页的自适应能力。
当元素定义为 float: left; 或 float: right; 浮动时,元素即成为了浮动元素,浮动元素具有一些块级元素的特征,但若没有给其定义宽度时,其宽度则为元素中内联元素的宽度。
浮动(Float)的概念是 CSS 中最让人感觉到困惑的一个理论知识。浮动的概念本身并不复杂,但是因为浏览器在开发时对 Float 的理论解读不同,造成了实际中的许多问题,尤其是 IE6 及以前的版本。
浮动的基本含义
浮动本身起源于实现图文环绕混排的目的。以下是我们经常用到的一个简单实例:
这是一个图文混合的例子,我们上传一张图片,图片在网页中的源代码定义为 style="float: right;" 。这里我们定义为图片定义了 float: right; 的属性,图片就在整段文字的左侧显示。在 Netscape(Netscape)1.1版时发布的“Additions to HTML 2.0”文档中,以“Float”(浮动)这个术语描述了在浏览器中,一个元素浮动至某一侧并停下的表现方式,CSS 中使用 float(浮动)属性来实现元素浮动的效果。浮动元素可以被移动至当前行的左侧或右侧,float 的属性及其值为:
float: left; 元素依据文本流位于对象的左边。
float: right; 元素依据文本流位于对象的右边。
float: none; 元素不浮动。
想要真正理解浮动理论,必须先明白在 CSS 中什么是行 (line box)。为了解释什么是行,必须先明白什么是行级元素。行级元素指的是那些非块级元素(如<em>),而行是一个逻辑上的概念,是一个虚拟的矩形,包含了组成该行的所有行级元素,其高度至少等于包含的最高的那个行级元素。
浮动元素的特性
1、浮动元素只能浮动至左侧或者右侧,没有浮动至中间一说,这是最基本的规则。
2、浮动元素会以水平的方向排列,以填充所在行的容器元素。如果其宽度足够挤满整行,则甚内容和元素不能围绕浮动元素。
3、和正常文档流中的元素有所差异的是,浮动元素的垂直边距(margin)不会叠加,上下二个浮动元素若都有垂直边距,则只会计算最大的那个垂直边距。
4、若浮动元素后面紧跟着块级元素,则浮动元素可以和临近在正常文档流中块级元素重叠。此时浮动元素不占正常块级元素文档流的空间,但是浮动元素会与块元素中的内容会依据文档流规则进行排列(具体可参阅《左中右三种页面布局样式备忘》一文)。
当一个元素浮动后,将自动转为块级元素的一部分属性(即转化为块状元素),如果元素本身是是内联元素,就会拥有了定义其高度和宽度的特性,而这个在内联元素本身是不可能实现的。所有的浮动元素应该设定其宽度属性(除非是<img>元素,因其具有隐含的宽度),如果不设定宽度,其布局结果将是不可预知的。
当我们让一个元素浮动,它会往左或者往右浮动,直至遇到所包含的容器(Containing blocks or containing boxes,指包含其他子元素的行级或块级元素的容器)的边缘。如果我们向同一方向再浮动一个元素,它会浮动直至碰到前一个浮动元素的边缘。如果我们浮动更多的元素,他们将一个挨一个排列,如果当前行的水平方向上没有足够的空间容纳浮动元素,则下一个浮动元素会换行至能容纳该元素的行继续排列。
当明确指定时,浮动元素垂直位置由它原先在文档流中的位置决定,顶端与当前行顶端对其。但是水平方向上,它尽可能远的向容器元素边缘移动,但是仍遵循容器元素的填充距离(padding)。同行的行内元素则围绕浮动元素排列。
由于浮动元素不占据正常文档流空间,所以浮动元素前后那些未明确指定位置的块级元素会占据浮动元素本来应该处在的位置,就好像它从来不曾存在过。而浮动元素之后的那行会根据浮动元素缩小宽度。浮动元素之前的元素则会重新被排列,占据独立的一行。(ie 和 ff 在这种情况下的表现不尽相同)
任何浮动元素都不可能超过原来所处文档留位置的上边界。浮动元素的顶端必定和当前行顶端对齐(或者在没有当前行元素时和前一个块级元素底部边缘对齐)。
浮动模型的基本特征简要归纳如下:
1、浮动模型不会与流动模型发生冲突。当 元素定义为浮动布局时,它在垂直方向上应该还处于文档流中,也就是说浮动元素不会脱离正常文档流而任意的浮动,它的上边线将与未被声明为浮动时的位置一样。但是在水平方向上,它的浮向边会尽可能地靠近它的包含元素边缘(这个边缘是指包含元素补白的内边)。例如,在上面的示例中,我们能够看到第 2 个 span元素虽然浮动位置有了变化,但依然处于第 1 个 span 元素后面,且靠近包含元素 body 的右边缘,并随文档流一起上下流动。
2、与普通元素一样,浮动元素始终位于包含元素内,不会游离于外,或破坏元素包含关系,这与层布局模型不同。
3、关于流动元素环绕问题。虽然浮动元素能够随文档流动,但 浮动模型与流动模型依然存在本质区别。浮动元素后面的块状元素和内联元素都能够以流的形式环绕浮动元素左右,甚至与上面的文本流连成一体。
4、关于浮动元素间并列显示问题。当两个或者两个以上的相邻元素都被定义为浮动显示时,如果存在足够的空间容纳它们,浮动元素之间可以并列显示。它们的上边线是在同一水平线上的。如果没有足够的空间,那么后面的浮动元素将会下移到能够容纳它的地方,这个向下移动的元素有可能产生一个单独的浮动。很多设计师喜欢使用浮动模型来布局网页,原因就在于它能够突破流动模型布局中块状元素不能并列显示的问题。
清除浮动
浮动元素之后的元素会自动围绕该浮动元素。如果不希望周围有元素围绕,则可以为这些元素定义“clear”属性以清除浮动。clear 的属性有及其值为:
clear: left; 清除左边的浮动对象,如果左边存在浮动对象,则当前元素会在浮动对象底下显示。
clear: right; 清除右边的浮动对象,如果右边存在浮动对象,则当前元素会在浮动对象底下显示。
clear: both; 清除左右两边的浮动对象,不管哪边存在浮动对象,当前元素都会在浮动对象底下显示。
clear: none; 默认值,允许两边都可以有浮动对象,当前元素浮动元素不会换行显示。
有很多技巧可以做到清理浮动元素,但不引入额外的无语义标签。下面三种是比较常见的做法:
1、插入一个使用不浮动的空区块(clear: both;)。
插入一个清除元素是使父级容器能正确包含其所有浮动元素是一种标准的做法(即插入一个非浮动区块<div class="clearbox"></div>),这样做能实现将父级容器的底部边缘“拖拉”以包裹所含元素的效果。
如果我们将 DIV 中所有的列都加上 float: left; ,这些 DIV 会挨个向左排列。如果我们希望在页面底部有一个页脚,并不需要一个最长的列,只要加上 clear: both 就可以了。
2、在容器元素上使用 overflow: hidden。
对于基于浮动设计的布局来说,一个常见的问题就是浮动元素的容器不会自动伸展来包含浮动元素。如果希望在所有的浮动元素的外面加上边框(如在容器元素上加上边框),这时必须告诉浏览器伸展容器以包含浮动元素,这时就可使用 overflow 的方法。
3、使用 :after 这样的 CSS 伪类。
使用 :after 来插入一个点号,并且设置它的属性为 clear: both;。但是容器底部会有一丝空隙,所以还要设置 height: 0px; 和 visibility: hidden; 来去除这个空隙。
具体清除浮动的代码和定义可以进一步参阅《清除浮动的一般解决方案》一文。
浮动清除只能适用浮动对象之间的清除,我们不能为非浮动对象定义清除属性,或者说为非浮动对象定义清除属性是无效的。但 IE 浏览器不支持这种标准。当一个浮动元素定义了 clear 属性,它不会对前面的任何对象产生影响,也不会对后面的对象形成影响,只会影响自己的布局位置。这里的影响是指不会主动改变别的对象的位置。浮动清除不仅针对相邻浮动元素对象,只要在布局页面里水平接触都会实现清除操作。
使用浮动元素包含浮动元素这样的布局方式有一个潜在的缺点,其实现效果将取决于浏览器的对 CSS 的支持与解析。特别是当浮动元素是一个更为复杂的布局中的一部分的话,将变得更加复杂。鉴于浏览器对流动模型解析的一致性,因此大多数时候,浮动模型只是作为流动模型布局的辅助与补充,这不失为一个很好的布局原则。