在 KB005: CSS 层叠 中已经介绍了 CSS 的重要之处。CSS 可以说是页面表现的基础, CSS 可以控制布局,控制元素的渲染。
布局是讲在电影画面构图中,对环境的布置、人物地位的调度、人物之间的关系、人物和景物的关系等的安排。大同小异,CSS 的布局也是一样。
CSS 的布局,包含两个大部分:
总的说来,CSS 的布局比电影场景布局简单的多,因为 CSS 中要控制的元素都是死的,而人是活的有思想的(无思想的道具除外~~)。
观察页面的构成元素,其中包括 SPAN DIV TABLE INPUT IMG 等等。
仔细观察每个元素,它们的形状都是矩形的,严格的说,元素形成了一个矩形的区域,这个区域就是 CSS 中最基本的布局要素, 常被称作 "box",你可以在很多 W3C CSS2.1 规范的原文中看到 "box" 这个字眼。本篇文章要讲的主要内容, 就是关于 "box" 组成及其变化的一系列规则,也就是今天要讲的内容:"Box Module",通常被译作“盒子模型”,有的地方被译作“框模型”。 因为 W3C 的很多地方用到了 "box" 这个词,有些地方译作“盒子”不大通顺,权且统统译作“框”。
本部分主要包括两部分:框的组成以及相关特性( property ),外边距折叠( Collapsing margins )。
为了给文档树中的各个元素排版定位(布局),浏览器会根据渲染模型1为每个元素生成四个嵌套的矩形框, 分别称作 content box、padding box、border box 和 margin box,它们是不可分割的,并可能会重合, 这就是 CSS 规范中描述的“框模型”(box model)。它是以 CSS 的角度去看一个元素被渲染后的抽象形态。 是一个元素自身的构成部分,不同于布局:多个元素在页面上的定位。
注:padding、border 和 margin 区域都包括 top、right、bottom、left 四部分。如图所示("LM" 代表 left
margin,"RP" 代表 right padding,"TB" 代表 top border……)。
上面的大框,代表一个元素生成的矩形区域( box ),每一个 box 都包括一个 content 区域(元素的内容,如文本,图形等)以及环绕其四周的 padding (元素的内边距,填充部分)、border (元素的边框) 和 margin (元素的外边距) 区域。
注:
上述四个区域(content、 padding、border 和 margin)分别有他们自己的边界,细化来说,每个区域都有 top、right、bottom、left 四个边界。
一个简单的例子,来自 W3C 官方:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <HTML> <HEAD> <TITLE>Examples of margins, padding, and borders</TITLE> <STYLE type="text/css"> UL { background: yellow; margin: 12px 12px 12px 12px; padding: 3px 3px 3px 3px; /* No borders set */ } LI { color: white; /* text color is white */ background: blue; /* Content, padding will be blue */ margin: 12px 12px 12px 12px; padding: 12px 0px 12px 12px; /* Note 0px padding right */ list-style: none /* no glyphs before a list item */ /* No borders set */ } LI.withborder { border-style: dashed; border-width: medium; /* sets border width on all sides */ border-color: lime; } </STYLE> </HEAD> <BODY> <UL> <LI>First element of list</LI> <LI class="withborder">Second element of list is a bit longer to illustrate wrapping.</LI> </UL> </BODY> </HTML>
示意图:
'margin' 是 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' 的简写,表明 margin 的大小范围。 它的值可以是 宽度值、百分比值或 'auto' 这3者之一,注意:宽度值必须带有单位。
margin 非 table 类型的元素,以及 table 类型中 table-caption, table 和 inline-table 这3类。例如 TD TR TH 等,margin 是不适用的。 并且,对于行内非替换元素(例如 SPAN),垂直方向的 margin 不起作用。
<div style="border:1px solid red;"> <span style="margin:100px; background:gray;">ddd</span> </div>
可以看到,DIV 的上下 border 紧贴着灰色的 SPAN 元素。
另外,垂直方向上的不同元素的相邻的 margin 在某些情况下,会发生折叠的现象。
padding 是 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' 的缩写。默认值是 0。
可以应用到的元素:除 display 值是 ‘table-row-group’,‘table-header-group’, ‘table-footer-group’, ‘table-row’, ‘table-column-group’ 和 ’table-column’ 的所有元素。
border 是 'border- top', 'border-right', 'border-bottom', 'border-left' 的缩写。
border 包含3个部分,’border-width’,’border- color’,’border-style’,分别用来设置它的宽度,颜色和样式。适用于任何元素。
border-width 是 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'。默认值是0。 可用值有‘thin’,‘medium’,‘thick’,以及常用的数值带单位的宽度值。
border-color 是 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color' 的简写。默认值是 ‘color’ 特性的值。
border-style 是 'border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style' 的简写。默认值是 none 特性的值。 可用值有:’none’,’hidden’,’dotted’,’dashed’,’solid’,’double’,’groove’,’ridge’,’inset’等。
注:
在介绍 margin 特性的时候,简单的介绍了外边距折叠。
Collapsing margins,即外边距折叠,指的是毗邻的两个或多个外边距 (margin) 会合并成一个外边距。
其中所说的 margin 毗邻,可以归结为以下两点:
下面详细的介绍其规则。
注:
两个或多个
说明其数量必须是大于一个,又说明,折叠是元素与元素间相互的行为,不存在 A 和 B 折叠,B 没有和 A 折叠的现象。
毗邻
是指没有被非空内容、padding、border 或 clear 分隔开,说明其位置关系。
注意一点,在没有被分隔开的情况下,一个元素的 margin-top 会和它普通流中的第一个子元素(非浮动元素等)的 margin-top 相邻; 只有在一个元素的 height 是 "auto" 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。
示例代码:
<div style="border:1px solid red; width:100px;"> <div style="margin:50px 0; background-color:green; height:50px; width:50px;"> <div style="margin:20px 0;"> <div style="margin:100px 0;">B</div> </div> </div> </div>
效果图:
以上代码中,margin 会把 B 的包含块撑开。
如果一个元素的 height 特性的值不是 auto,那么它的 margin-bottom 和它子元素的 margin-bottom 不算相邻,因此,不会发生折叠。 margin-top 没有此限制,所以是 100px,margin-bottom 没有折叠,只有 50px。
垂直方向
是指具体的方位,只有垂直方向的 margin 才会折叠,也就是说,水平方向的 margin 不会发生折叠的现象。
例子:
<div style="height:50px; margin-bottom:50px; width:50px; background-color: red;">A</div> <div style="height:50px; margin-top:100px; width:50px; background-color: green;">B</div>
示意图:
在 margin 都是正数的情况下,取其中 margin 较大的值为最终 margin 值。
当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移。
示例代码:
<div style="height:100px; margin-bottom:-75px; width:100px; background-color: red;">A</div> <div style="height:100px; margin-top:-50px; margin-left:50px; width:100px; background-color: green;">B</div>
示意图:
如果,毗邻的 margin 中有正值,同时存在负值会怎样呢?有正有负,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。
示例代码:
<div style="height:50px; margin-bottom:-50px; width:50px; background-color: red;">A</div> <div style="height:50px; margin-top:100px; width:50px; background-color: green;">B</div>
示意图:
上面的例子最终的 margin 应该是 100 + (-50) = 50px。
要注意,相邻的元素不一定非要是兄弟节点,父子节点也可以,即使不是兄弟父子节点也可以相邻。
而且,在计算时,相邻的 margin 要一起参与计算,不得分步计算。
一个复杂的实例:
<div style="margin:50px 0; background-color:green; width:50px;"> <div style="margin:-60px 0;"> <div style="margin:150px 0;">A</div> </div> </div> <div style="margin:-100px 0; background-color:green; width:50px;"> <div style="margin:-120px 0;"> <div style="margin:200px 0;">B</div> </div> </div>
错误的计算方式:算 A 和 B 之间的 margin,分别算 A 和其父元素的折叠,然后与其父元素的父元素的折叠,这个值算出来之后,应该是 90px。依此法算出 B 的为 80px;然后,A和B折叠,margin 为 90px。
请注意,多个 margin 相邻折叠成一个 margin,所以计算的时候,应该取所有相关的值一起计算,而不能分开分步来算。
以上例子中,A 和 B 之间的 margin 折叠产生的 margin,是6个相邻 margin 折叠的结果。将其 margin 值分为两组:
根据有正有负时的计算规则,正值的最大值为 200px,负值中绝对值最大的是 -120px,所以,最终折叠后的 margin 应该是 200 + (-120) = 80px。
浮动元素的 margin 在垂直方向上也不会发生 margin 折叠,即使和它相邻的子元素也不会。
<div style="margin-bottom:50px; width:50px; height:50px; background-color:green;">A</div> <div style="margin-top:50px; width:100px; height:100px; background-color:green; float:left;"> <div style="margin-top:50px; background-color:gold;">B</div> </div>
示意图:
两个绿色的块儿之间,相距100px,而若 B 和它的浮动包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,显然,没有发生折叠。
以 “overflow : hidden” 的元素为例:
<div style="margin-top:50px; width:100px; height:100px; background-color:green; overflow:hidden;"> <div style="margin-top:50px; background-color:gold;">B</div> </div>
若 B 和它的 "overflow:hidden" 包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,否则,没有发生。
示意图:
自身 margin-bottom 和 margin-top 相邻,只能是自身内容为空,垂直方向上 border、padding 为 0。
示例:
<div style="border:1px solid red; width:100px;"> <div style="margin-top: 100px;margin-bottom: 50px;"></div> </div>
以上代码运行后,我们讲得到的是红色边框的正方形,方框的宽高都应该是 100px,高度不应该是 150px。
示意图:
注:
相关浏览器对此部分内容引起的兼容性问题,可以参考:
操作系统版本: | Windows 7 Ultimate build 7600 |
---|---|
浏览器版本: |
IE6
IE7 IE8 Firefox 3.6.10 Chrome 7.0.517.0 dev Safari 5.0.2 Opera 10.62 |
测试页面: | |
本文更新时间: | 2010-09-19 |
框模型 Box module Collapsing margin 折叠