前台开发从头说起:理解css盒模型

在掌握了丰富而强大的之后,就具备了将css样式根据需要应用到网页中任何元素的能力。能够应用规则了,接下来就需要熟练掌握规则的制定方法——什么样的属性组合能够实现什么样的效果。一般的颜色、字体、字号、行高等的设置比较容易掌握,而初学者在应用css的时候,主要头疼的还是如何用css实现复杂的网页布局,从两栏布局、三栏布局,到表单设计等。在布局的时候,实际上主要是借助元素的宽、高、定位、浮动、边距、边框、间距、背景颜色、背景图片的组合来实现的。而所有这些,都要基于对css盒模型的理解。网上对盒模型的论述很多(推荐阅读《彻底理解css盒子模式》),我这里想从实用的角度来谈谈。

网上有两张著名的图片,分别以2D和3D的形式描述css盒模型:

图片1

cssbox3d

通过这两张图,一般来说对于margin、border、background-color、background-image、padding以及width和height有较直观的了解了。

更为重要的是要了解以下几点:

  1. 对于所有以“块(block)”方式呈现的元素都具备这个模型的特性,而不只是div;
  2. margin是以所指定元素的父级元素(常称为“容器”)为基准的;
  3. 一个元素(通常为块元素)在页面中所占的位置尺寸为:宽度= width + padding-left + padding-right + border-left-width + border-right-width + margin-left + margin-right;高度 = height + padding-top + padding-bottom + border-top-width + border-bottom-width + margin-top + margin-bottom;(部分浏览器有差异,以后再具体讨论);
  4. background-color将填满border内部的全部范围;background-image默认以图片左上角对齐border内部左上角点,然后完整显示整个图片(超出部分不予显示),如果图片尺寸不足铺满整个范围,图片默认重复自己直至铺满或超出范围;
  5. background-image将叠加到background-color之上;通过指定图片的对齐方式,可以改变background-image的位置;

通过以上这些规则的组合,就能在有限的元素组合下,实现各种修饰性效果。一个简单的例子如下:

将一个15像素高,颜色为#c00的纯色图片c00 放入一个高度为30像素,背景色为#f00的块元素,设定图片在Y轴方向不平铺,在x轴方向平铺。结果得到一个类似下图的效果:

c00f33

这是简单的由背景色与背景图组合实现的效果。根据这样的原理,当我们的文档结构有两层时,例如:<a href=”#"><span>文字</span></a>,我们可以通过由a元素的背景颜色图片和span元素的背景颜色图片组合,从而得到较为复杂的效果,例如:

button

这个按钮效果,用纯图片很容易实现,但是用图片实现就会面临一个问题:不通用。如果要通用,应该把文字和背景图片分离开来,同时,由于文字有多有少,因此按钮的宽度要是可变的,但是按钮并不是从左到右完全一致的背景,于是不能使用一张图片进行横向平铺,按照以前的做法,可能会使用一个一行三列的表格,第一个单元格放入左侧的图片,中间的单元格放文字和平铺的背景,右边的单元格放右侧的图片。这种思维传递到了“div+css”布局思维模式下,于是就出现了这样的结构:

<div class=”button”><div class=”left”></div><div class=”center”></div><div class=”right”></div>

这个结构的出现,就是为了实现自适应宽度的按钮,今天依然存在。实际上,使用上面的a+span的基本结构,就能实现这个效果。将中间平铺部分和左侧或右侧的边缘图片组合在一起,重复部分做得宽一些,作为a的背景图片,把另一侧的图片作为span的背景图片覆盖到a的背景图片上。组合起来看上去就成为一个整体。代码如下:

效果如下:

image

a {display:block;width:200px;height:36px;background:url(button.gif) no-repeat right bottom;}
a span {display:block;line-height:36px;background:url(button.gif) no-repeat left top;color:#fff;text-decoration:none;text-align:center;}

用到的背景图片如下:

button 

这个例子很简单,但是需要对“背景组合”有足够的理解,能够想到应用。而要想到如此应用,首先是对于盒模型中的“background”足够的理解。否则,就只会想到三个div(或者其它元素组合方式),但是由于左右两个结构完全一样,为了区分它们,只好使用class或者id来标记。这就是我在中所提到的不必要的class和id。

除了利用display:block让行内元素改变为块元素从而使用盒模型特征外,在浮动的时候,也经常会用到盒模型的一些特征。再举个例子:

使用浮动布局的时候,并列呈现的浮动元素中的第一个如果设置与浮动方向相同的margin,则IE 6下会出现margin加倍的bug(这就是著名的IE6浮动边距加倍bug)。为了解决这个问题,很多人喜欢给一组浮动元素的第一个加上class=”first”,从而可以对这个元素单独应用样式。或者对这一组浮动元素加上display:inline的属性以解决这个bug。

上述两种方式都是没有使用hack选择符或者类似“_margin”这样的非标准属性的很好的hack方式。但是,如果不是非用margin不可,只要使用padding来代替margin,就能解决这个问题。或者采用与浮动方向相反的margin也可以。不需要任何额外的hack。这也是在充分理解盒模型的基础上,由于对这个bug的了解,从而在实现样式的时候直接避开,而不是出现了之后再用额外手段去hack。

对盒模型的理解,除了margin、border、padding、width、height五大属性以及两种背景的应用之外,还要了解父级元素与子元素之间的关系。比如父元素没有设置尺寸,而对子元素设置margin-top属性,在某些浏览器下,本来是想针对父元素的边缘设置margin,结果margin被设置到了父元素之外,造成父元素与外部元素的margin。这种情况,将子元素的margin改成父元素的padding,也可以在不改变表现的情况下实现相同的效果。

要想通过对盒模型特征的充分应用来减少css中的hack使用,或者以更简洁的代码实现更复杂的效果,需要对盒模型不断地尝试和总结。这是《css权威指南》之类的经典巨著也没法教给你的。

只有越理解盒模型,才能越好地利用浮动和定位来实现复杂、精确的布局。关于浮动的问题,下一次我们再一起来了解一下。

本条目发布于。属于CSS分类,被贴了 标签。
               

前台开发从头说起:理解css盒模型》上有3条评论

评论已关闭。