从一篇外文谈谈盒模型 - 小南帝
从一篇外文谈谈盒模型
声明:作为初涉前端的老菜鸟,在对知识的理解上肯定会出现些许偏差,在此先向各位看官提个醒,呵呵。我认为,理解盒子模型是学好整个CSS的关键之关键基础。本文借鉴http://www.chinaz.com/design/2010/1229/151993.shtml(翻译篇)的基础上,重新翻译了http://www.sitepoint.com/web-foundations/css-box-model/(纯英文)这篇文章,再加上自己的理解,谈一谈盒模型。
翻译外文:
对盒子模型(box model)概念的理解,以及盒子模型如何决定某个元素最终尺寸,将有助于你理解一个元素如何在网页中进行定位。盒子模型主要适用于块级元素。顺便提一个与此相关的概念:行内布局模型(inline layout model)——定义了行内元素是如何定位的,在行内元素格式(Inline Formatting)中有具体说明。
计算盒子尺寸
在CSS2.1中,块级元素都是以矩形显示。我们计算一个块级元素的整体尺寸,需要包括内容区域(the content area)的宽高,以及这个元素被赋予的所有外边距(margin)、内边距(padding)和边框(border)。
我们可以通过声明和定义一个元素的宽度和高度属性来定义这个元素的内容的宽度。如果不给出声明,这个元素宽度和高度的缺省属性就是浏览器默认的。
对于静态元素(没有定位的)和设置相对定位的元素,他们的宽度是默认的,即这一元素的宽度是其包含块(即最近的父元素)的宽度减去所有横向的外边距、内边距和边框以及滚动条。也就是说,这一元素的宽度就是其包含块的宽度减去自身横向上所有外边距、内边距、边框和滚动条(如果有的话)所剩余的宽度。
包含块的尺寸和定位是其子元素尺寸和定位的参考。尽管元素的定位依照他们的包含块,但是又不完全依照包含块,这些元素也可以溢出他们的包含块。大多数情况下,对于子盒子来说,generated boxes扮演包含块的角色。关于包含块的更多细节请参照Containing Block.
专栏:浮动元素和他们的宽度起先,在CSS2中,没有声明宽度的浮动元素不会收缩至紧紧包裹其内容,而是与他们的父元素保持一样的宽度。在CSS2.1中,这种情况发生了改变,没有声明宽度的浮动元素将会紧紧包裹其内容。然而,在IE6和更早的版本中,一个没有声明宽度的浮动元素将默认紧紧包裹其内容,除非他的一个子元素设置了布局,在这种情况下,浮动元素的宽度会延伸至充满整个可用内容区域。另外有一种情况需要说明,当一个没有设置宽度的浮动元素包含一个右浮动的子元素时,该浮动元素的宽将与其父元素保持一致。这种浮动的情况在之前的IE浏览器,包括IE7中都是存在的(之前的Firefox,包括2.0版本中也存在,其实这是一个bug。但是这个问题在Firefox3.0 Alpha 6 版本中已经得到了解决)。 因此,为避免出现上述bug,尽量给浮动元素设置一个明确的宽度,在网页布局时总是会安全一些。然而,只要你注意上述问题,你会发现,无宽度的浮动元素在某些特定情况下总是有用的,比如在横向流式布局菜单中(fluid-width horizontal menus).
|
对于宽度为auto的浮动或者绝对定位的元素(包含设置固定定位),他们会使generated box在尺寸上收缩至紧紧包含内容。
如果没有设置高度或者最小高度和最大高度,无论内容区域如何设置定位,它的高度将和内容的高度保持一致。
因此,为弄清一个元素在网页中需要的总体空间,需要将内容区域的内边距、边框和外边距都加上。当然,一个元素可能没有设置任何的内边距、边框和外边距,这种情况下,它的尺寸将有自身的内容支撑。
如果一个元素仅包含浮动或者绝对定位的元素,它将没有任何内容,它的高度将为0。这一问题我们将在Floating and Clearing这篇文章中阐述。
盒模型的实现
Total width = left margin +left border + left padding + width + right padding + right border + right margin Total height = top margin + top border + top padding + height + bottom padding + bottom border + bottom margin |
下面这个小案例将最好地描述盒模型。我们用运算的方式弄清楚一个元素在网页中显示到底需要多大的空间(忽略外边距塌陷,我们将在下面的内容详细讲解)。如下:
.box { width: 300px; height:200px; padding:10px; border:1px solid #000; magin: 15px; } |
这是我们CSS案例—为一个类名为box的元素声明所有的盒子属性:
计算上面这个盒子的总体尺寸如下:
Total width = 15+1+10+300+10+1+15=352px;
Total height = 15+1+10+200+10+1+15=252px;
下图形象展示了具体的尺寸,这个图是通过Firebug截取的。
在上图中,我们清晰地看到,内容区域(蓝色部分)居*,内边距、边框和外边距环绕。内容区域的外边缘称为内容边缘(content edge),或者是内边缘(inner edge);内边距区域的外边缘被称为外边距边缘(padding edge);边框区域的外边缘被称为边框边缘(border edge);外边距区域的外边缘被称为——你应该可以猜到了——外边距边缘(margin edge)或外边缘(outer edge)。
从这个小案例你可以看出,为了将这个元素显示在网页上,我们至少需要一个宽为352px、高为252px的空间。如果可用的空间比这个空间稍微小一点,元素就会发生错位,或者溢出。值得注意的是,IE6和早期的版本会尽可能的将包含这一元素的最近父元素进行伸展,以足够盛下这一元素,这将打乱网页布局。其他的浏览器会允许元素溢出,并忽略掉溢出内容。
专栏:留意外边距合并 在上面的计算中,尽管将外边距计算在元素所需的空间大小中,但是需要注意的是,标准流中垂直方向上的相邻元素的外边距会出现合并,并且合并后的外边距是两者中较大的那个。也就是说,计算相邻元素中的一个元素所需要的实际空间大小,并不需要从该元素外边距的最边缘算起,只有最大的外边距才生效,较小的外边距会被最大的外边距吞噬而融入大边距。具体详细讲解可查看Collapasing Margins. |
盒模型的实际应用
非常值得注意的一点是,如果给一个元素的宽度设置100%(也就是说,宽度百分百继承其父元素),这个元素不应该有任何的外边距、内边距和边框,这将使得该元素需要更大的显示空间。这一现象经常被设计师忽略,并且会严重扰乱网页布局,因为内容要么溢出要么使元素比他们应该有的宽度大。
大多数情况下,解决这一问题的方式是避免添加具体的宽度值(不是自动值),而是只应用外边距、内边距和边框。标准流中元素的宽度属性是默认的,即使设置外边距、内边距和边框,它仍然认为可用的宽度区域是全满状态。
当然,这种方法在某些情况下并不起作用,比如元素不是标准流中的元素,并且需要一个固定的宽度(就如我们上边举的浮动元素不会自动伸展填满它的父元素)。遇到这种现象,你有两种方式可选择。
如果可用空间是固定宽度的,你只需给元素设置各类属性值(margin 、padding、width等),使可属性值的和刚好匹配可用空间的宽度。例如:可用空间的宽度如果为500px,你需要元素拥有20px的内边距,那么可以将宽度设置为460px,内边距设置为20px(20+460+20=500)。这一方式的前提是宽度值和元素盒子属性使用相同的测量单位,因为你不希望把混合单位相加起来吧(200px+10%,只是举个例子,在内容中这样的写法没有任何意义)!
如果可用空间的宽度是未知的,例如在流式布局中,这种方法将不起作用,因为百分比和像素是不能相加的。这样的话,解决方式就是给元素的宽度设置为100%,并且给其嵌套的元素设置内边距、边框和外边距值。这个嵌套元素没有设置具体的宽度,并且能够在不干扰父元素的情况下显示所需的内边距、边框和外边距。
这篇文献研究盒模型的前提是块级元素的盒模型,主要从以下几方面进行讲解:
- 盒模型在网页中显示所需空间实际大小的计算,分标准流和脱离标准流两种状态。
1)在标准流状态下,不给元素声明宽度,元素宽度默认为父元素的宽度。一旦声明宽度,将以声明的宽度进行显示,并且在宽度超过父元素的情况下会发生溢出,溢出部分不会被隐藏。
在此举个例子:
html中的代码:
标准流下的元素
|
CSS中的代码:
.box1 { width: 200px; height: 200px; background-color:pink; }
.box2 { height: 100px; padding: 10px; background-color:blue; color:white; } |
在Firefox中的显示如下:
可以看出,蓝色的盒子没有设置宽度,它的宽度默认为其父元素粉色盒子的宽度。但是,当给蓝色的盒子设置的宽度大于父盒子粉色盒子的时候,蓝色盒子会溢出,并且会覆盖的
2)脱离标准流情况下,对于宽度设置为auto的浮动元素 或者绝对定位元素或者固定定位元素,它将紧紧包裹自身的内容,而不是保持与父元素一样的宽度。
如上述例子中的box2设置如下:
.box2 { width:auto; height: 100px; background-color:blue; color:white; float:left; } |
结果如下:
可以看出,蓝色的盒子(box2)的宽度为auto的情况下,它不会跟其父盒子保持一样的宽度,而是紧紧包裹其内容区。
3)如果父盒子和子盒子都设置浮动,父盒子在不设置宽度的情况下,在IE7及以前的版本中,仍将与其父元素的宽度保持一致;在其他浏览器中将紧紧包裹其子元素。
上一篇: Python内置数据类型详解