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

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

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

通过这两张图,一般来说对于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的纯色图片

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

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

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

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

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

效果如下:

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;}

用到的背景图片如下:

这个例子很简单,但是需要对“背景组合”有足够的理解,能够想到应用。而要想到如此应用,首先是对于盒模型中的“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权威指南》之类的经典巨著也没法教给你的。

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

资源 | 23种Pandas核心操作,你需要过一遍吗?

Pandas 是基于 NumPy 构建的库,在数据处理方面可以把它理解为 NumPy 加强版,同时 Pandas 也是一项开源项目。它基于 Cython,因此读...

722
来自专栏Python小屋

详解Python列表推导式

列表推导式可以使用非常简洁的方式对列表或其他可迭代对象的元素进行遍历和过滤,快速生成满足特定需求的列表,代码具有非常强的可读性,是Python程序开发时应用最多...

3114
来自专栏bboysoul

1165: C语言实验题――三个整数

描述:给出三个整数,请你设计一个程序,求出这三个数的和、乘积和平均数。 输入:输入只有三个正整数a、b、c。 输出:输出一行,包括三个的和、乘积、平均数。数...

564
来自专栏阿凯的Excel

文本数字拆分技巧

Excel处理人员呢,最喜欢的就是规范化的表,那什么样子的表是规范的呢?给大家个图片感受一下! ? 今天的要和大家分享的就是和规范化图表格格不入的,需要由不规...

2736
来自专栏小白客

每天学习一点儿算法--快速排序

快速排序是一种常用的优雅的排序算法,它使用分而治之的策略。 那么分而治之(D&C)是一种怎样的策略呢? 分而治之 分而治之(D&C)的要点只有两个: 找出简单...

2724
来自专栏java一日一条

使用Java 8函数式编程生成字母序列

在 Java 8 中使用函数式编程生成字母序列是一个很大的挑战。Lukas Eder 愉快地接受了这个挑战,他将告诉我们如何使用 Java 8 来生成ABC的序...

342
来自专栏CDA数据分析师

资源 | 23种Pandas核心操作,你需要过一遍吗?

Pandas 是基于 NumPy 构建的库,在数据处理方面可以把它理解为 NumPy 加强版,同时 Pandas 也是一项开源项目。它基于 Cython,因此读...

752
来自专栏大数据杂谈

【Excel系列】Excel数据分析:数据整理

1. 直方图的功能 “直方图”分析工具可计算数据单元格区域和数据接收区间的单个和累积频率。此工具可用于统计数据集中某个数值出现的次数,其功能基本上相当于函数FR...

2187
来自专栏take time, save time

你所能用到的数据结构(五)

七、骚年,这就是你的终极速度了吗? 在介绍了前面的几个排序算法之后,这一次我准备写写快速排序,快速排序之所以叫快速排序是因为它很快,它是已知实践中最快的排序算...

2685
来自专栏aCloudDeveloper

公司数据结构+算法面试100题

1.把二元查找树转变成排序的双向链表(树) 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。 ...

4529

扫码关注云+社区