大家好!这篇教程是关于框模型的。在开始之前先熟悉下很快会用到的术语:元素内容、内边距、边框、外边距。下面会给大家一个简单的印象。开始之前,务必在编辑器内打开 HTML 的源文件。

如果你正在看源代码,也就是 HTML 文件的内容,你会看到这段话是包含在 p 标签里面。顺便说一句,如果想在网页上显示尖括号的话,在源代码里面直接打一个尖括号是不行的,这样浏览器在解析 HTML 文件的时候,会以为你开了个新的标签。所以要用 < 和 > 来代替。对比一下HTML文件的内容和浏览器打开的效果。再顺便说一句,用 <code> 标签可以让文字变成等宽字体。这个网页里多处用到了这个标签


内边距

本段落的 ID 是 #border-only-1。你发现这个段落有一个非常黑的边框,边框跟字挨得非常紧。

本段落的 ID 是 #padding-and-border-2。跟上一段一样也有个黑边框,不过离文字远了一些,看起来舒服一点。也就是说——在「元素内容」和「边框」之间,有一定量的「内边距」。请看源码顶部的 <style> 标签里面,p#padding-and-border-2 选择器里头,比 p#border-only-1 多了个 padding 属性。padding 就是「内边距」的英文。

本段落的 ID 是 #padding-explained-3。内边距的作用很单纯,就是在边框跟内容之间创造一点空间。所以内边距永远是透明的。除了宽度,基本没办法定制。所以最常见的就是 p { padding: 5px; } 这样的。不过,每个方向的内边距宽度可以不一样。试试 padding-left 之类的属性。其他三个方向的英文是 right, top, bottom。一般来说,单位是 px,也就是像素。其他的长度单位也可以。

练习:给上一段随便加个边框,然后设定下内边距。

练习:给四个方向设定不同的内边距。


外边距

本段落的 ID 是 #padding-and-border-again-4。接下来我们来看「外边距」。这一段有设定内边距和边框,但是还没有设定外边距。

本段落的 ID 是 #padding-border-and-margin-5。这一段加了外边距。观察下 <style> 里面就知道,这一段多了一个 margin 属性。

本段落的 ID 是 margin-explained-6,马上大家要对这个ID对应的CSS进行修改。margin 的作用是让一个「框」和另外一个「框」保持距离。常用的也只是调节四个方向的距离。此外,有一个叫「外边距合并」的现象,对应英文 margin collapsing。这个现象常常让人头疼,一般来讲就是竖直方向的上下两个「框」之间的外边距会重叠在一起,只剩较大的那个。具体有不同的情况,如果想深入了解,请参阅这里

练习:给上一段随便加个边框,接着设定下内边距,最后加个外边距。

练习:你可能已经注意到了。观察一下,你在做前一个练习的时候,有没有「外边距合并」的情况?#padding-border-and-margin-5 这一段默认有 40px 的外边距。可以试试给 margin-explained-6 设定 20px 的外边距,再改成 40px。这两个「框」之间的距离会有变化吗?再试试设定成 80px。


什么是「框」?

我提了好多次「框」(box)这个字,那它究竟是指什么东西?

一个 HTML 文件里面,这些用一对标签括起来的东西,都叫「元素」。比如说这一整个段落是个元素。前几段有个链接,那个由 <a> 标签括起来的,它也是个元素。就连前一句话的 <code> 标签括起来的也是。不过它们还是有一些区别的。<p> 是一个「块级元素」(block element),<a><code> 是「行内元素」(inline element)。这个很好理解吧?块级元素自带换行(注意到没?你从来不需要在段落和段落之间手动换行),行内元素显然不用换行。块级元素还包括 <h1>, <h2> 这样的,行内元素还有图片、粗体、斜体、下划线等等。

每个块级元素都会产生一个「框」,包括元素内容(就是这些真正的内容,文字图片视频什么的)、内边距和边框。外边距不算是框的一部分,因为那是框之间的距离。「框模型」就是 CSS 提供的一个排版系统,用来安排每个框之间的位置关系。一个网页就可以看成是一个个的「框」组合起来。

框模型示意图


框模型的宽度

不知道你有没发现,在 #border-only-1#padding-and-border-2 的 CSS 中,我写的都是 width: 800px;,但是这两个段落显然没有对齐,后面那段的「框」明显比前面那段的「框」要宽出来一截。这是因为,width 规定的是元素内容的宽度,而不是整个框的宽度。要让这两个框(包括内容、内边距和边框)的宽度统一为 800px,也就是说考虑进内边距和边框本身的宽度,要在 CSS 里面加上这么一条:

box-sizing: border-box;

如果不特别写出来,这项 box-sizing 属性的默认值是 content-box。这个应该不用再解释了。最后,没有 margin-box,因为外边距不属于框的一部分。

练习:#border-only-1#padding-and-border-2 的 CSS 加上 box-sizing: border-box;。观察一下效果


块级元素和行内元素的结合

刚刚在讲块级元素和行内元素的时候,我提到块级元素自带换行。这个「换行」不是指文字另起一段,指的是,如果你在 HTML 里面连续写上两个 <p> 元素,后一个段落一定会在前一个段落下面,不会在它右边,即使你限定了宽度,即使右边还有空间。

这里是 p1。它的宽度是 40vw,也就是浏览器宽度的 40%。这样它的右面一定有 60% 的空间。而下面一段的CSS属性和这一段一样,宽度同样是浏览器宽度的40%,然而它并不会被移到这一段的右面,即使右面空白的地方完全足够放下它。

这里是 p2。它的宽度同样是 40vw。大家可以看到这种情况下它会被放到p1的下面。而右面是很大的空白空间。这个显然和常见的网页排版不一样,看起来很奇怪。

如果你想弄个分栏效果,让两个段落并排站,可以在 CSS 里面加上一句:

display: inline-block;

练习:加在哪里呢?思考一下。

练习:不能用 display: inline;。你试试就知道为什么。思考下为什么结果是这样的,它跟 inline-block 的区别在哪里。


本课总结题:

练习:有没有觉得现在这个网页很丑?很大一部分原因是,太宽了。你想想,哪有书会把字印到书页的最边缘。所以,想个办法,给网页内容跟浏览器的左右两边之间加点空隙。