网页开发入门|09 盒模型
W3C标准中把每个元素都看作是一个小盒子,从而处理元素间的边距问题。

在上节课,我们了解了如何在网页中设定颜色。通过准确的设定颜色,文章页面的配色看起来和谐多了。

本节课来解决边距和间距的问题。

对比设计稿,我们目前的成稿中有三处明显距离问题:
- 标题与段落,以及段落之间的间距;
- 作者名和朝代的间距;
- 标签中字与背景框的边距。
盒模型Box model
在CSS
中是使用盒模型box model来处理边距问题的。
什么是盒模型呢?
W3C标准中把每个元素都看作是一个小盒子,就下面这样:

盒子与盒子之间的距离称作外边距margin,盒子里装的东西与盒子边之间的距离称作内边距padding,盒子里装的东西称作内容content,盒子本身的外壳称作边框border。

与上面图中的首饰盒不同的是,在页面中的元素都是二维的,把盒子拍扁之后就是这样:

如图,内边距padding、边框border、外边距margin,围绕内容content在上下左右四个方向存在,且都可以有一定的尺寸(可以理解为厚度)。
随着技术的发展,对盒模型的理解有两个版本,一个是早期的IE版的盒模型,一个是如今的标准盒模型,主要的区别是对元素宽度的理解不同。
在IE浏览器的年代,元素的宽度width指的是包含了边框的元素的宽度,而在现代浏览器中,元素的宽度width指元素中内容的宽度。
其实这两种盒模型之间是可以相互换算的,但后者逐渐成为了今天的主流,可能是因为今天的开发者更关心的是盒子里面装的内容的尺寸,而不是盒子本身的尺寸吧。
本教程中强烈推荐大家使用Edge或Chrome浏览器,所以我们会使用标准盒模型,即把元素宽度理解为内容的宽度。
盒模型的代码实现
让我们新建一个box.html
来看看盒模型的效果,代码如下:
<head>
<style>
div {
margin: 20px;
border: 2px solid red;
padding: 20px;
width: 100px;
background-color: lightgray;
}
</style>
</head>
<body>
<div>hello, world!</div>
</body>

在CSS
代码中,我们设置了margin,border,padding,width,background-color五个属性,可以在图中看到他们的效果:
- margin是这个元素与周围其他元素之间的距离,因为左侧和上侧是浏览器的边框,右侧和下方并没有其他的元素,所以左侧和右侧看起来窄一些,实际的距离就是代码中设定的20px;
- border我们设定为了2px宽的红色实线(solid),这是我们第一次遇到需要多个值的样式属性,多个属性之间需要使用空格隔开;
- padding使得边框在上下左右所有方向上都距离内容有20px,但因为content中文字的实际宽度不到
100px
,所以看起来文字距离左右两侧边框的距离并不一致; - width只能对块元素设定,行内元素的width会永远和里面内容的保持一致;
- background-color的有效范围是包含padding部分的。
如果我们只需设置上下左右其中一个方向的margin,border,padding,有两种方法设定。
以值设定左padding为例:
方法一,直接使用更准确的样式属性padding-left
:
div {
padding-left: 20px
}

方法二,以上、右、下、左的顺序,分别写出四个方向具体的值,以空格隔开:
div {
padding: 0 0 0 20px;
}
如果我们想只区分上下和左右的话,还可以写两个值:
div {
padding: 0 20px;
}

如果在配合上单方向边框,还会有些特别的效果。
div {
padding: 0 20px;
border-bottom: 2px solid red;
}

div {
padding: 0 20px;
border-left: 2px solid red;
}

块元素的调整
让我们先来解决目前成稿中块级元素之间的边界问题。
为了不影响之前已经生效的代码,建议再复制一下上节课peom4.html
为poem5.html
,在新文件中改造它。
为了方便使用CSS
选择器,咱们先给页面中的一些主要部分添加一下id
属性,必要的地方还会套一层div
标签:
<body style="font-family: STKaiti, KaiTi">
<h1 id="title">登鹳雀楼</h1>
<div id="author" style="font-size: 0.9em;">
<!-- 此处省略部分代码 -->
</div>
<hr>
<div id="content">
<p>白日依山尽,黄河入海流。</p>
<p>欲穷千里目,更上一层楼。</p>
</div>
<div id="tag" style="font-size: 0.9em; font-family: STSong, SimSun">
<!-- 此处省略部分代码 -->
</div>
<p id="photo">
<img src="assets/王之涣.jpg" alt="王之涣" />
</p>
</body>

块级元素都是独占一行的,所以对边距的调整更多是来调整元素间在垂直方向上的距离。
目前设计稿中的这些块级元素,都没有画出边框,也没有背景色,所以从代码实现的角度来说,无论使用padding或者margin都可以调整元素间的距离,完全看不出来区别。
但我们更加推荐使用margin来定义元素间的间距,padding更适合实现每个元素自己的样式,比如缩进等效果。这也是外边距和内边距原本的含义。
更好的办法还是以设计师给出的设计稿为准。

作为一个开发向的课程,我们不展开如何从设计稿中获取各元素的样式信息的办法,因为这与设计师所使用的设计软件有关。我们假设已经从设计师处了解到了具体的数值了。
废话不多说,直接上代码。
/* 省略无关代码 */
#title {
margin: 13.4px 0;
padding: 0 5px;
}
#author {
margin: 10px 0;
}
#content {
margin: 15px 0 5px 0;
padding: 0 5px;
}
#content p {
margin: 5px 0;
}
#tag {
margin: 13px 5px;
}

行内元素的调整
目前页面里需要修改的行内元素是a
,需要调整作者名后面的间距,以及标签部分的每个标签的样式。
与块级元素不同,行内元素会排列在同一行内,所以对行内元素的调整更多的是水平方向的调整。
与块级元素相似,元素间的间距调整应该使用margin,每个元素自己的效果,应该使用内边距。
同样,我们直接以设计师给出的参数,对这些a
元素的效果进行调整:
/* 省略无关代码 */
#author a {
margin-right: 30px;
}
#tag a {
background-color: #f1f2f6;
margin: 2px 5px;
padding: 2px 5px;
}

行高
调整完了内外边距,我们发现在垂直方向显得更加的紧凑了,行与行之间的距离怎么比设计稿里又小了呢?是我们调整错了参数么?
当然不是啦!行间的间距变小了是因为影响垂直方向间距的,还有一个重要因素——行高line-height。
让我们回到box.html
中,将div
的宽度设置为50px
。
div {
margin: 20px;
border: 2px solid red;
/* padding: 0 20px; */
width: 50px;
background-color: lightgray;
}

因为50px不足以在一行内排列整个句子,所以发生了自动换行。可以清楚的看到,行与行之间并没有紧紧的挨在一起,而是出现了一个空隙。

同时请注意,我们在代码中明确的取消了padding效果,但是hello, world!
距离上下边缘还都有一定的距离。

带来这两个地方空隙的就是行高。
如果行内的字比行高要大,实际的行高就是字的高度;如果行内的字比行高要小,多出来的行高将均匀的分布在字的上下方。

因为行高有这样的特性,所以通常有两个作用:
- 用于多行的元素,设定行间距,提升阅读体验;
- 用于单行的元素,使其内容在垂直方向上居中。
好了,了解了行高的作用,让我们回到poem.html
,根据设计稿把行高属性也设定进去:
/* 省略无关代码 */
body {
line-height: 1.5em;
}
#author {
line-height: 19px;
}
#content p {
line-height: 25px;
}

延伸阅读:用盒模型绘图
通过设定元素的盒模型属性,可以在页面中绘制一些图形。
矩形
绘制矩形比较容易,设定好元素的宽、高、背景色即可。
<style>
.rectangle {
width: 100px;
height: 50px;
background: red;
}
</style>
<div class="rectangle"></div>

圆角矩形
边框还有设定圆角能力,可以将矩形设定为圆角矩形。
<style>
.round-rectangle {
width: 100px;
height: 50px;
background: red;
border-radius: 20px;
}
</style>
<div class="round-rectangle"></div>

椭圆/圆
当圆角矩形的圆角尺寸刚好是所在边的一半,就可以形成一个椭圆形。
<style>
.oval {
width: 100px;
height: 50px;
background: red;
border-radius: 50%;
}
</style>
<div class="oval"></div>

当然,如果原本是个正方形,那就可以得到一个圆形。
<style>
.circle {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
}
</style>
<div class="circle"></div>

三角形
借助边框的能力,还可以绘制出三角形。
对一个宽高都为0的元素,四个方向边框加上不同的颜色,可以得到这样的图形。
<style>
.colorful-border {
width: 0px;
height: 0px;
border-left: 50px solid red;
border-right: 50px solid yellow;
border-top: 50px solid green;
border-bottom: 50px solid blue;
}
</style>
<div class="colorful-border"></div>

如果我们只保留一遍的颜色,然后其余边框设为透明,即可得到三角形。
<style>
.triangle {
width: 0px;
height: 0px;
border-left: 50px solid red;
border-right: 50px solid transparent;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
}
</style>
<div class="triangle"></div>

画出这些形状与什么用呢?
其实用的地方还蛮多的,很多页面中的小细节都是靠这些能力实现的。比如微信聊天的气泡,就是一个小三角和一个圆角矩形的结合。

我将本课程所有的代码托管在gitee
上了,你可以点击这个链接,或到gitee.com
上搜索弦五 网页开发入门,查看和获取本课程的全部代码。