要掌握的三个最重要的CSS概念是浮动、定位和框模型。这些概念控制在页面上安排和显示元素的方式,形成CSS的基本布局。如果你习惯于用表格控制布局,那么这些概念初看上去可能有点儿奇怪。实际上,大多数人只有在使用CSS开发站点一段时间之后,才能完全掌握框模型的复杂性、绝对定位和相对定位之间的差异以及浮动和清理的实际工作方式。在切实掌握这些概念之后,使用CSS开发站点就会变得容易多了。
在本章中,你将学习:
- 框模型的复杂性和特性。
- 如何以及为什么使用空白边叠加。
- 绝对定位和相对定位之间的差异。
- 浮动和清理是如何工作的。
2.1 框模型概述

#myBox {
margin: 10px;
padding: 5px;
width: 70px;
}
填充、边框和空白边可以应用于一个元素的所有边,也可以应用于单独的边。空白边还可以是负值,并且在多种技术中都要使用负值的空白边。
2.1.1 IE/Win 和框模型
不幸的是,IE 5.x 和 IE 6 在怪异模式中使用自己的非标准框模型。这些浏览器的 width 属性不是内容的宽度,而是内容、填充和边框的宽度总和。这实际上有一定的意义,因为在现实世界中框具有固定的尺寸,而且填充是放在框里面的。添加的填充越多,给内容留下的空间就越少。尽管符合逻辑,但是这些 IE 版本不符合规范,这会造成严重的问题。例如,在前面的示例中,在 IE 5.x 中框的总宽度只有 90 像素。这是因为 IE 5.x 认为 每个边上 5 像素的填充是 70 像素的宽度的一部分,而不是在宽度之外附加的 (见图 2-3)。

幸运的是,有几个方法快可以解决这个问题,这些方法的细节可以在第 9 章中找到。但是,目前最好的解决方案是回避这个问题。也就是,不要给元素添加具有指定宽度的填充,而是尝试将填充或空白边添加到元素的父元素或子元素。
2.1.2 空白边叠加
空白边叠加是一个相当简单的概念。但是,在实践中对网页进行布局时,它会造成许多混淆。简单地说,当两个垂直空白边相遇时,它们将形成一个空白边。这个空白边的高度等于两个发生叠加的空白边的高度中的较大者。
当一个元素出现在另一个元素上面时,第一个元素的底空白边与第二个元素的顶空白边发生叠加 (见图 2-4)。




这就是一系列空的段落元素占用的空间非常小的原因,因为它们的所有空白边都叠加到一起,形成一个小的空白边。
空白边叠加初看上去可能有点儿奇怪,但是它实际上是有意义的。以由几个段落组成的典型文本页面为例 (见图 2-8)。第一个段落上面的空间等于段落的顶空白边。如果没有空白边叠加,后续所有段落之间的空白边将是相邻顶空白边和底空白边的和。这意味着段落之间的空间是页面顶部的两倍。如果发生空白边叠加,段落之间的顶空白边和底空白边叠加在一起,这样各处的距离就一致了。

*****只有普通文档流中块框的垂直空白边才会发生空白边叠加。行内框、浮动框或绝对定位框之间的空白边不会叠加。*****
2.2 定位概述
既然已经熟悉了框模型,我们就来看看视觉格式化模型和定位模型。理解这两个模型的细微差异是非常重要的,因为它们一起控制着如何在页面上布置每个元素。
2.2.1 视觉格式化模型
p、h1 或 div 等元素常常称为块级元素。这意味着这些元素显示为一块内容,即 "块框"。与之相反,strong 和 span 等元素称为行内元素,因为它们的内容显示在行中,即 "行内框"。
可以使用 display 属性改变生成的框的类型。这意味着,通过将 display 属性设置为 block,可以让行内元素 (比如锚) 表现得像块级元素一样。还可以通过将 display 属性设置为 none ,让生成的元素根本没有框。这样,这个框及其所有内容就不显示,不占用文档中的空间。
****CSS 中有三种基本的定位机制:普通流、浮动和绝对定位。****
除非专门指定,否则所有框都在普通流中定位。顾名思义,普通流中元素框的位置由元素在 (X)HTML 中的位置决定。
块级框从上到下一个接一个地排列;框之间的垂直距离由框的垂直空白边计算出来。
行内框在一行中水平布置。****可以使用水平填充、边框和空白边调整它们的水平间距 (见图2-9) 。但是,垂直填充、边框和空白边不影响行内框的高度。****由一行形成的水平框称为行框,****行框的高度总是足以容纳它包含的所有行内框。但是,设置行高可以增加这个框的高度。****


在这种情况下,这个框称为无名块框,因为它不与专门定义的元素相关联。
块级元素内的文本行也会发生类似的情况。假设有一个包含三行文本的段落。每行文本形成一个无名行框。无法直接对无名块或行框应用样式,因为没有可以应用样式的地方。但是,这有助于理解在屏幕上看到的所有东西都形成某种框。
2.2.2 相对定位
相对定位是一个非常容易掌握的概念。如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直或水平位置,让这个元素 "相对于" 它的起点进行移动。如果 top 设置为 20 像素,那么框将出现在原位置顶部下面 20 像素的地方。如果将 left 设置为 20 像素,那么会在元素左边创建 20 像素的空间,也就是将元素向右移动 (见图 2-10) 。

在使用相对定位时,无论是否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其他框。
2.2.3 绝对定位
相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。与之相反,绝对定位使元素的位置与文档流无关,因为不占据空间。普通文档流中其他元素的布局就像绝对定位的元素不存在时一样 (见图 2-11) 。

绝对定位的元素的位置相对于最近的已定位祖先元素。如果元素没有已定位的祖先元素,那么它的位置相对于最初的包含块。根据用户代理的不同,最初的包含块可能是画布或HTML 元素。
与相对定位的框一样,绝对定位的框可以从它的包含块向上、下、左、右移动。这提供了很大的灵活性。可以直接将元素定位在页面上的任何位置。
对于定位的主要问题是要记住每种定位的意义。相对定位是 "相对于" 元素在文档流中的初始位置,而绝对定位是 "相对于" 最近的已定位祖先元素,如果不存在已定位的祖先元素,那么是最初的包含块。
因为绝对定位的框与文档流无关,所以它们可以覆盖页面上的其他元素。可以通过设置 z-index 属性来控制这些框的堆放次序。z-index 值越高,框在堆中的位置就越高。
绝对定位的元素的位置相对于最近的已定位祖先元素,这使我们能够实现一些非常有意思的效果。例如,假如希望让一个文本段落对准一个大框的右下角。只需对包含框进行相对定位,然后相对于这个框对段落进行绝对定位:
#branding {
width: 700px;
height: 100px;
position: relative;
}
#branding .tel {
position: absolute;
right: 10px;
bottom: 10px;
text-align: right;
}
<div id="branding">
<p class="tel">Tel: 0845 838 6163</p>
</div>
相对于相对定位的祖先元素对框进行绝对定位,这在大多数现代浏览器中实现得很好。
*****但是,在 Windows 上的 IE5.5 和 IE6 中有一个 bug。如果试图相对于相对定位的框的右边或底部设置绝对定位的框的位置,那么需要确保相对定位的框已经设置了尺寸。如果没有,那么 IE 会相对于画布定位这个框。****
在第9章可以进一步了解这个 bug 和修复方法。简单的解决方案是为相对定位的框设置宽度和高度,从而避免这一问题。
在进行页面布局时,绝对定位是非常有用的工具,尤其是在使用相对定位的祖先元素的情况下。完全可能只使用绝对定位创建出整个设计。为此,这些元素需要具有固定尺寸,这样就能够将它们定位在任何地方而不会有重叠的风险。
因为绝对定位的元素与文档流无关,所以它们不影响普通流中的框。如果扩大绝对定位的框 (例如,通过增加字号),周围的框不会重新定位。因此,尺寸的任何改变会导致绝对定位的框产生重叠,从而破坏精心调整过的布局。
固定定位
固定定位是绝对定位的一个子类别。差别在于固定元素的包含块是视口。这使我们能够创建总是出现在窗口中相同位置的浮动元素。这种情况的一个示例可以在 snook.ca 上看到 (见图 2-12)。博客评论表单采用固定定位,这使它在页面滚动时一直出现在屏幕上的相同位置。这有助于改进易用性,用户不必为了发表评论而一直滚动到页面底部。

不幸的是,IE6和更低版本不支持固定定位。为了解决这个问题,Jonathan Snook 使用 JavaScript 在 IE 中重现了这个效果。
2.2.4 浮动
最后一种定位模型是浮动模型。浮动的框可以左右移动,直到它的外边缘碰到包含框或另一个浮动框的边缘。
****因为浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样。****
如图 2-13 所示,当把框 1 向右浮动时,它脱离文档流并且向右移动,直到它的右边缘碰到包含框的右边缘。





