XHTML 中大部分的元素(特别是块状元素)都可以看做一个盒子,即使是 body、html 这些元素本身也是个盒子,而网页的元素的定位,实际上就是将众多大大小小的盒子在页面中进行布局和定位。这些盒子在页面中是“流动”的,当某个块状元素被 CSS 设置了浮动属性,这个盒子就会“流”到上一行,这些问题在前几章中我们已经作了深入的探讨。网页布局即关注这些盒子在页面中如何摆放、如何嵌套的问题,而这么多盒子摆在一起,最需要关注的是盒子尺寸计算、是否流动等要素。
CSS 2.0 中的盒模型是关系到我们排版定位的关键,例如<div>就遵循盒模型规范。盒模型定义中主要是 margin、padding 、background(background-color、background-image)、border 和 content 属性,XHTML元素的特性和一个盒子非常相似,它们之间的层次、关系和相互影响如图所示:
CSS 2.0 盒模型平面示意图:
网上流传着另一张由 w3c 提供的 cssbox 3D 图片(点击查阅“cssbox3d.gif”图片)示意其层次、关系。在这张 3D 示意图中,元素的 CSS 属性从前往后依次是 border、padding 和 content、background-image、background-color、margin,border 属性位于层的最上方,这样可以从三维立体上理解为:
border 属性-层叠(或覆盖)-padding 属性和 content 属性-层叠(或覆盖)-background-image 属性-层叠(或覆盖)-background-color 属性-层叠(或覆盖)-margin 属性
事实是不是这样呢?利用晚上空闲时间画了这这张“CSS 2.0 盒模型 3D 示意图”,方便分析:
CSS 2.0 盒模型 3D 示意图:
从上面的图片中可以看出,padding 属性和 content 属性-层叠-background-image 属性-层叠-background-color 属性,这个是存在的,它们三者之间构成了 Z 轴(垂直屏幕的坐标)多重层叠关系。
但是 border 属性与 margin 属性、padding 属性三者之间应该是平面上的并级关系,并不能构成 Z 轴的层叠关系。下面我们对 单个 XHTML 元素的这几个属性作一下分析:
1、 单个 XHTML 元素的 CSS 属性中,margin、border 、padding 这三个属性分别起着外边界、边框和内间距的作用:
(1) margin 属性可以设置为负值,但将 margin 属性设置为负值时,则是针对元素自身整体与其他元素间进行定位,margin 属性为负值时影响不到元素本身的其他属性。
(2) padding 属性不可以设置为负值,与margin、border 和 content 属性始终处于平面的关系,没有 Z 轴的层叠关系。
(3) border 属性也不可以设置为负值,与margin、padding 和 content 属性始终处于平面的关系,没有 Z 轴的层叠关系。。
因此,对于 单个 XHTML 元素本身而言,margin、border 、padding 这三个属性是在同一个平面上,只可以在 X 轴、 Y 轴(水平与垂直的平面坐标)进行横向和纵向的布局,不可以在 Z 轴上进行上下层叠(这里我们说的是单个 XHTML 元素的属性)。尤其是 margin 和 padding 这二个属性,主要是控制边距和缩进,即使是用负值,也只是将元素本身与其他元素之间、元素内容与边框之间定位控制,而不存在上下层叠的关系。
2、单个 XHTML 元素的 border 属性、padding 属性和 content 属性,与背景属性 background(包括 background-color 和 background-image 这二个属性)之间,只构成上下的 Z 轴层叠关系。
多重层叠关系立体的 CSS 2.0 盒模型 3D 示意图:
3、当单个 XHTML 元素同时定义 margin、padding 、background-color、background-image、border 和 content 这6个属性在时,元素就同时存在着 X 轴(横向)、Y 轴(纵向)和 Z 轴(垂直)多重层叠关系,其效果类似于一个立体的盒子,所以可以形象称之为“盒模型”。用通俗的话讲,横向、纵向构成了 CSS 模型的宽度和高度,垂直构成了 CSS 模型的厚度,这样就构成了类似于立体的 box 模型。
因此,w3c 提供的 cssbox3d 图片的示意中将 margin 位于最后、border 位于最前的立体关系是有误导的,在单个 XHTML 元素中 margin 、padding 和 border 属性永远不可能上下层叠。
至于多个 XHTML 元素之间,我们可以利用 CSS 属性中的 z-index 属性来实现定位元素的层叠等级,这个是针对多个元素间的布局与定位的关系,已经超出了单个 XHTML 元素的盒模型关系(有兴趣可以进一步请查阅《布局模型(4)层模型的特征》一文)。
大多数 XHTML 元素(包括 html 元素和 body 元素)的结构都类似于上图中所示,除了包含的内容(文本或图片)外,还有内边距、边框和外边距一层层的包裹。只有在布局网页和定位 XHTML 元素时要充分地考虑到这些要素,才可以更自如地摆弄这些盒子。
外边界属性即 CSS 的 margin 属性,CSS 中可拆分为 margin-top(顶部外边距)、margin-bottom(底部外边距)、margin-left(左边外边距)和margin-right(右边外边距)。CSS 的边框属性(border)和内边距属性(padding)同样可拆分为 4 边。在 Web 标准中,CSS 的宽度(width)和高度(height)属性即为盒子所包含内容的宽度和高度:
盒子宽度 = padding-left + border-left + margin-left + width + padding-right + border-right + margin-right
盒子高度 = margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom
但是由于目前各厂商的浏览器对网页模型理解的差异,同时浏览器在 CSS 盒模型和网页模型的实现上也并没有完全遵照 W3C 所倡导的标准化,因此在实际应用中各浏览器的解析在统一性上存在一定的问题,相信随着时间的推进,标准之路将是大趋所至,因此深入理解 CSS 盒模型的原理显得尤为重要。
下面就几个容易模糊或误解的地方再强调一下:
1、margin 总是透明的,padding 也是透明的,但 padding 受背景影响,能够显示背景色或背景图像,所以部分初学者会误认为补白不透明。
2、border 不透明,这是因为实线边框的遮盖。当你定义虚线或点线边框时,在部分浏览器中可以看到被边框遮盖的背景。盒模型背景可以深入到 padding 和 border 区域,但部分浏览器不支持 border 区域背景显示,如 IE 和 Netscape 浏览器。
3、margin 可以定义负值,但 border 和 padding 不支持负值。
4、margin、border 和 padding 都是可选的,它们默认值为 0。我们可以单独定义一边或统一定义盒子四边的属性值。
5、如果需要,每一条可见边框都可以定义不同的宽度,但前提是要定义 borderstyle 属性为可见样式。
6、每一个盒子所占页面区域的宽度和高度等于 margin 外沿的宽度和高度。盒子的大小并不总是内容区域的大小。
7、浏览器窗口是所有元素的根元素,也就是说 html 是最大的盒子,也有浏览器把 body 看作最大的盒子。