现在我们已经熟悉了HTML和CSS。了解了它的基础。现在我们来更深入的了解元素在页面中的呈现和大小。

在这节课中,我们将会讨论什么是盒子模型,它的工作模式是怎样的。我们也会在课程中学习一些新的CSS属性,并且将介绍三种长度单位。

元素是如何显示的

在了解盒子模型之前,我们先来了解一下元素是如何显示的。在第二节课中,我们学习了块状元素和内联元素的差异。快速回顾一下,块状元素会另起一行,并占据所有可用的宽度,不管内容有没有。而内联元素会并排显示,宽度紧随内容变化而变化。块状元素通常用在大块的内容上,例如标题,结构元素。内联元素用在小块的内容上,比如将几句话加粗或斜体显示。

display属性

元素如何显示——例如块状元素,内联元素和其他元素——都由显示属性 display 决定。每个元素都有一个默认的 display 属性值。和其他属性值一样,这个属性值是可以被覆盖的。 display 值有很多,其中最常用的是 blockinlineline-blocknone

我们可以通过CSS选中元素并改变和重新声明元素的 display 属性值。 若值为 block 可以使元素成为块状元素显示。

p {   display: block; }

将值设置为 inline ,可以将元素转化为内联元素。

p {   display: inline; }

inline-block 比较有意思,它可以使元素的所有块状元素的属性生效。但元素又按照内联元素显示,不会另起一行。

p {   display: inline-block; }

两个内嵌块元素间的空隙

inline-block 内嵌块元素有个重要的点,就是它们并非是首尾相接的。两个内嵌块元素之间存在小空隙。这个空隙虽然很恼人,但这是正常现象。我们会讨论为什么这个空隙存在,以及怎么消除。

最后是 none 属性值,会完全隐藏元素,页面渲染的时候会当它不存在。任何被包裹在这个属性值元素内的元素都会被隐藏。

div {   display: none; }

了解元素如何显示,以及怎么修改 display 属性非常重要,因为它会影响盒子模型的呈现效果。讨论盒子模型的时候,我们会知道他们之间的差别,意义和影响。

什么是盒子模型?

根据盒子模型的概念,每个在页面上的元素都是一个拥有宽,高,内边距,边框和外边距的长方形盒子。

页面上每个元素都符合盒子模型的定义,所以它非常重要。我们使用一些新的CSS属性来来熟悉它。

使用盒子模型

每个元素都是一个长方形盒子,有几个属性能确定这个盒子的大小。盒子的核心属性是元素的宽高,这两个值可能是由元素的 display 属性、元素的内容或具体的 widthheight 属性值生成的。内边距 padding 和边框 border 拓展了元素的高宽。最后是我们定义的在边框外的外边距 margin

盒子模型对应的CSS属性为: widthheightpaddingbordermargin

我们来看例子:

div {   border: 6px solid #949599;   height: 100px;   margin: 20px;   padding: 20px;   width: 400px; }

根据盒子模型,元素的总宽度计算如下:

margin-right + border-right + padding-right + width + padding-left + border-left + margin-left

[译]HTML&CSS Lesson4: 盒子模型

使用上述公式,就能算出示例中的高宽值

  • Width:492px = 20px + 6px + 20px + 400px + 20px + 6px + 20px

  • Height:192px = 20px + 6px + 20px + 100px + 20px + 6px + 20px

毫无疑问盒子模型是HTML和CSS很容易混淆的部分之一。

我们将 width 的值设置为 400 像素,但元素的实际宽度为 492 像素。默认情况下,盒子模型是加法。因此想要确定盒子的实际大小,我们需要考虑将四面的内边距,边框,外边距都考虑进去。宽度不仅仅是 width 属性的值,也要加上左右两侧的内边距,边框和外边距。

到目前为止,上述属性看着没什么实际意义。因为这只是为了澄清所有形成盒子模型的属性: widthheightpaddingbordermargin

宽度和高度

每个元素都有默认的高度和宽度。虽然宽度和高度都有可能是 0 像素,但默认情况下,浏览器会渲染每个元素的大小。元素的默认宽度和高度依赖于元素是怎么显示的。如果元素是页面布局的关键元素。那么它就需要设置具体的 widthheight 属性值。这种情况下,只能指定非内联元素的属性值。

宽度

元素的默认宽度依赖于它 display 属性的值。块状元素的默认宽度为 100% ,占据整行空间。内联元素和内嵌块元素的宽度都随着元素的内容变化而变化。内联元素不具备固定的大小,所以 widthheight 属性只有在非内联元素上才能生效。如下是为非内联元素设置宽度的例子:

div {   width: 400px; }

高度

元素的默认高度取决于它的内容。元素根据内容需要进行垂直扩展或收缩。我们可以使用 height 属性为非内联元素设置高度:

div {   height: 100px; }

调整内联元素

请记住内联元素不支持 widthheight 属性和与其相关的值。块状元素和内嵌块元素支持 widthheight 属性和与其对应的值。

外边距和内边距

浏览器会根据元素设置其默认的外边距和内边距,使其更清晰易读。我们使用基于文本的元素来看一下这个现象。不同浏览器和不同元素之间的默认外边距和内边距可能存在差异。我们在第一课中有讨论过CSS重置,将这些差别调低,或使其为零。这样我们就可以从头开始定义我们需要的样式。

外边距

margin 属性设置一个元素的周围空间大小。外边距在元素边框外并且是完全透明的。外边距可以帮助我们将元素定位在页面的特定位置,并且可以与其他元素保持距离。 示例如下:

div {   margin: 20px; }

margin 有一个特殊的现象,就是在内联元素中垂直外边距 margin-topmargin-bottom 不生效,在块状元素和内嵌块元素中有效。

内边距

padding 属性和 margin 属性相似,只不过它在边框内部, padding 是为元素提供内部空间。示例如下:

div {   padding: 20px; }

padding 属性和 margin 属性不一致的地方是垂直内边距在内联元素中同样有效;虽然垂直内边距显示在元素基准线之上或之下,但是它确实是存在的。

内联元素的外边距和内边距

内联元素对内边距和外边距的实现和块状元素与内嵌块元素不同。外边距只有横向 margin-leftmargin-right 有效。内边距在内联元素中完全生效,但是垂直内边距 padding-toppadding-bottom 在元素基准线上面或下面显示(译者注:内联元素加上垂直内边距之后,元素内部的内容部分在视觉上没有产生偏移)。

块状元素和内嵌块元素的外边距和内边距的显示是正常的。

外边距和内边距的声明方式

在CSS中,很多属性都有多种声明方法。普通的写法,就是一个属性一个值,一个个地列出来。但我们也可以使用简写,一个属性包含多个值。不是所有的属性都有简写,所以我们必须确保写出的属性和值的结构是正确的。

marginpadding 有普通和简写两种书写方式。当元素四面设置相同的外边距时,可以使用 margin 属性,并只指定一个值:

div {   margin: 20px; }

如果上下外边距的值一致,左右外边距的值一致,我们可以输入两个值。 设置上下外边距的值在前面。以下例子将上下外边距设置为 10 像素,将左右外边距设置为 20 像素:

div {   margin: 10px 20px; }

如果四个值都不一致,那么我们按照 上右下左 的顺序输入值。例如,我们为 div 设置 10 像素的顶部外边距, 20 像素的右侧外边距, 0 像素的底部外边距,以及 15 像素的左侧外边距:

div {   margin: 10px 20px 0 15px; }

若我们要设置多个值,优先考虑用 marginpadding 。但我们也可以用普通写法,输入一一对应的属性和值。每个属性名(该例子中是外边距和内边距)后跟随一个破折号 - 以及要设置值的盒子的方向: topbottomrightleft

例如, padding-left 属性只接受一个值,设置元素的左侧内边距; margin-top 只接受一个值,设置元素的顶部外边距。

div {   margin-top: 10px;   padding-left: 6px; }

当我们只想设置单边的 marginpadding 值时,这种普通写法是最好的选择。保持代码的精确性可以防止出现混淆。例如,我们是否只想将元素的上右左三侧的外边距设为 0 ,是否只想将底部外边距设为 10 像素?

普通写法输入属性和值可以让目标更明确。当处理三个或以上的值时,缩写更有帮助。

外边距和内边距的颜色

marginpadding 属性是完全透明的,不可以设置颜色。但因为是透明的,所以透出了相关元素的背景色。元素外边距部分看到的颜色为它父级元素的背景色。元素内边距部分看到的颜色为该元素的背景色。

边框

边框在内边距和外边距之间,画出了元素轮廓。 border 属性要求三个值:宽度,样式,颜色。边框属性简写时值的顺序为:宽度,样式,颜色。普通书写方式下,边框的三个属性名为: border-widthborder-styleborder-color 。普通书写方式因为是单个值,更容易修改和复写。

边框的宽度和颜色能分别使用第三节课中讨论过的长度单位和色值。

边框有很多 不同样式 。最常用的样式值为 soliddasheddottednone ,但你可以在列表中看到很多其他的样式。

以下是边框设置示例:

div {   border: 6px solid #949599; }

[译]HTML&CSS Lesson4: 盒子模型

单侧边框

marginpadding 属性一样,也可以一次只设置元素一个方向的边框。使用属性名: border-topborder-rightborder-bottomborder-left 。它们的属性值和 border 的属性值一样有三个:宽度,样式和颜色。如下所示:

div {   border-bottom: 6px solid #949599; }

另外,单侧边框的样式也可以被细分,如下所示:

div {   border-bottom-width: 12px; }

这些高度细分的边框属性名都由连字符分隔,由border单词开头,随后是边框的方向: toprightbottomleft ,最后是要设置的样式: widthstylecolor

border-radius

border-radius 可以使元素的边角变圆。

border-radius 接受多种长度单位,如百分比,像素,确定元素边角变圆的半径。单个值表示四个角的弧度一直,两个值按分别表示 top-left / bottom-righttop-right / bottom-left ,输入四个值按顺序分别表示: top-lefttop-rightbottom-rightbottom-left

思考 border-radius 多个值的顺序时(包括 marginpadding ),记住它们是从左上角开始( marginpadding 从上侧开始)按顺时针方向排序的。

div {   border-radius: 5px; }

[译]HTML&CSS Lesson4: 盒子模型

border-radius 属性也允许我们使用普通方法书写单个属性值。这些普通的属性以 border 单词开通,跟着是边角的垂直位置( topbottom ),再是边角的横向位置( leftright ),最后是半径 radius 。例如,要设置 <div> 右上角的边角半径,可以使用 border-top-right-radius 属性:

div {   border-top-right-radius: 5px; }

box-sizing

现在,在盒子模型中有一个附加属性。如果你设置了元素的 width400 像素,并将 padding 设置为 20 像素,将 border 设置为 10 像素,那么实际的盒子宽度为 460 像素。记住,盒子的宽度是 width , paddingborder 相加获得的。

但是在CSS3中,盒子模型有了一个不一样的计算方式。CSS3推出了 box-sizing 属性,完全改变了盒子模型的运作模式和元素大小的计算方式。这个属性有三个主要值—— content-boxpadding-boxborder-box ——每个值对盒子模型大小的计算稍微有些不一样。

content-box

content-box 这个属性值是默认值。这个默认值和元素不加 box-sizing 属性时的效果是一致的。元素从 widthheight 属性的值开始计算,加上 paddingbordermargin 属性值获得盒子的实际尺寸。

div {   -webkit-box-sizing: content-box;      -moz-box-sizing: content-box;           box-sizing: content-box; }

特定浏览器的属性和值

上例中 box-sizing 属性前的连字符和字母是什么?

CSS3的推出后,浏览器逐步开始以加前缀的方式支持新属性和值,包括 box-sizing 属性。随着部分CSS规范被浏览器广泛支持以及浏览器版本的更新,前缀的作用也越来越小,随着时间的发展将不再是一个问题。但在老版本浏览器中还是不可或缺的。

属性名和属性值都可以添加前缀。例如,上例中的 box-sizing 属性名加了前缀。浏览器可以选择什么时候加前缀什么时候不加前缀,因此有些属性需要带有某浏览器的前缀,有些属性不需要。

接下来的课程中,若某个属性或值需要前缀,只会在介绍那个属性时添加使用(这有利于保持代码的简洁)。不过你们在实际写代码的时候不要忘记添加前缀。

最常见的几个浏览器前缀概括如下:

  • Mozilla的火狐浏览器: -moz-

  • 微软的IE浏览器: -ms-

  • Webkit(谷歌的Chrome浏览器和苹果的Safari浏览器): -webkit-

padding-box

属性值 padding-box 时,元素将 padding 属性值计算入 widthheight 属性值内,改变了盒子模型计算模式。例如,元素的 width 设置为 400 像素, padding 值设为 20 像素,最终元素实际的宽度还是 400 像素。随着内边距的扩大,元素的内容区域会随着缩小,但是盒子实际大小并未发生改变。

如果我们增加 bordermargin ,那么盒子的大小就是这些属性值加上 widthheight 的值。例如,我们将元素的的 width 设置为 400 像素,每个方向的 border 都设置为 10 像素, padding 设置为 20 像素,那么元素的实际宽度就为 420 像素。

div {   box-sizing: padding-box; }

值 padding-box 已被弃用

随着CSS规范的更新, box-sizing 的值 padding-box 已被弃用,我们不应再使用它。

Border Box

最后一个属性值是 border-box ,它将 borderpadding 都算在元素的 widthheight 属性值内。例如,一个元素的 width400 像素,每边的 padding20 像素, border10 像素,最终元素的实际宽度仍然为 400 像素。

若我们还增加了 margin 属性,在获取盒子总大小时它的值需要做加法计算。不管 box-sizing 的属性值是什么, 计算盒子总大小时任何 margin 的值都需要做加法计入。

div {   box-sizing: border-box; }

[译]HTML&amp;CSS Lesson4: 盒子模型

使用box-sizing属性

通常来说, box-sizing 最佳属性值为 border-box ,这个属性值更易计算。如果我们将一个元素的 width400 像素,那么不管你增加了边框还是内边距,它的大小都还是 400 像素。

另外,我们也可以轻松的相对值。如果我们设置一个元素的宽度为 40% ,元素每边的 padding 值为 20 像素, border 值为 10 像素。那么尽管有地方设置了像素值,元素盒子的实际大小仍然为 40%

唯一遗憾的是 box-sizing 是CSS3的属性,并不是所有浏览器都支持,尤其是老版本浏览器。所幸随着浏览器版本更新,影响会越来越小。我们使用 box-sizing 的时候,需要留意哪些浏览器会出现兼容问题。

开发者工具

大多数浏览器都有 开发者工具 。我们可以使用这些工具查看页面上的元素、这些元素的HTML结构

和CSS属性及它们值。它们大部分都有盒子模型图解。

在Chrome浏览器中打开菜单栏,找到“更多工具”选项中的“开发者工具”选项并点击它,浏览器窗口的底部会显示出一个视窗,其中提供了一些代码检查工具。

悬停或点击视窗中的元素节点,可以查看这个元素的信息。

选中一个元素后,在视窗右侧选中“Computed”选项,我们就可以看到我们选中的元素的盒子模型。

Chrome, Firefox,Safari以及其他浏览器中都有开发者工具。查看源代码可以学到很多东西。我在编写HTML和CSS的时候通常都会打开开发者工具,也常常用它查看分析其他网站的源代码。

[译]HTML&amp;CSS Lesson4: 盒子模型

练习

现在我们回到之前做的“样式讨论会”网站,并未它添加更多的内容。

  • 首先,在 main.css 文件中添加一个 box-sizing 属性,值设置为 border-box ,这样可以使我们的元素更容易控制。在文件的页面重置样式下,添加一条注释,有助于网站布局。把它放在样式重置代码之下,是使其放在正确的层叠关系上。

    在这里,我们可以使用通配符选择器 * ,后面跟随带伪元素的选择器 *:before*:after ,这样就可以选中页面中所有的元素,将其 box-sizing 值设置为 border-box 。请记住, box-sizing 是有前缀的,因为它是一个较新的属性。

/*   ========================================   Grid   ======================================== */  *, *:before, *:after {   -webkit-box-sizing: border-box;      -moz-box-sizing: border-box;           box-sizing: border-box; }
  • 接下来我们要创建一个可以作为我们元素容器的class属性。用它在不同的元素上设置共同的 widthpadding 属性,并将元素居中。 在我们通配符选择器下,创建一个新的class选择器名为 container 。在选择器中将 width 设置为 960 像素, padding-leftpadding-right 设置为 30 像素,上下外边距设置为 0 ,左右外边距设为 auto

    container 告诉浏览器所有使用了这选择器的元素的宽度。左右外边距值设为 auto ,再加之设好的宽度值,可以让浏览器自动计算出左右相等的外边距,元素就相对于页面居中了。最后设置左右内边距,使内容不紧贴元于素的边缘,为内容提供一点喘息的空间。

.container {   margin: 0 auto;   padding-left: 30px;   padding-right: 30px;   width: 960px; }
  • 现在 container 已经可以使用,我们把它添加到所有页面的 <header><footer> 元素上,所有页面包括 index.htmlspeakers.htmlschedule.htmlvenue.html 以及 register.html 页面。

<header class="container">...</header>  <footer class="container">...</footer>
  • 接下来,我们将 container 添加到介绍会议的 <session> 元素和包含 <section> 作为子元素的`<section>元素上。

<section class="container">...</section>
  • 另外,也将 container 添加到其他页面中包含有 <h1> 元素的 <section> 元素上。

<section class="container">   <h1>...</h1> </section>
  • 稍后我们还会再回来调整这些元素和class属性。现在我们先做另一件事。

  • 现在我们的内容已经居中显示,接下来为元素创建纵向的间隔。我们先把标题和段落的底部外边距设置为 22 像素。我们将这个排版样式以及它的注释放在之前的容器样式之下。

/*   ========================================   Typography   ======================================== */  h1, h3, h4, h5, p {   margin-bottom: 22px; }
  • 我们在此跳过了 <h2><h6> 元素,因为设计中 <h2> 不需要外边距, <h6> 这次我们不会用到。

  • 现在我们在页面第一个 <section> 的底部放置一个按钮,并为其设置边框和圆角。

    我们先添加一个 <a> 元素,并将其的class属性值设为 btnbtn-alt .

<a class="btn btn-alt">...</a>
  • 接下来我们在排版样式之下为这两个属性值添加样式。

  • 首先创建一个能被所有按钮共享的样式的class选择器 btn 。我们希望所有的按钮的 border-radius5 像素, displayinline-block ,并移除所有外边距。

/*   ========================================   Buttons   ======================================== */  .btn {   border-radius: 5px;   display: inline-block;   margin: 0; }
  • 我们使用 btn-alt 为当前按钮设置特殊的样式。我们增加1像素的灰色边框,并且设置上下内边距为 10 像素,左右内边距为 30 像素

.btn-alt {   border: 1px solid #dfe2e5;   padding: 10px 30px; }
  • 我们在同一 <a> 元素中使用了 btnbtn-alt ,那么相应的样式都会渲染上去。

  • 在主页上,我们为包含上述 <a> 元素的 <section> 元素设置 padding 样式。我们通过在其上添加一个class属性值 hero 来实现。

<section class="hero container">   ... </section>
  • 最后,我们在CSS文件分隔出一块专门设置主页的样式,然后 hero 添加 padding 属性。

/*   ========================================   Home   ======================================== */  .hero {   padding: 22px 80px 66px 80px; }

现在我们的网站更加完整了,尤其是主页。

[译]HTML&amp;CSS Lesson4: 盒子模型

通配符选择器

在此练习的第一步,我们提到了通配符选择器 * ,它会选中所有的元素。相比于一一列出所有能想到的单个元素,不如使用它来选中所有的元素。

我们也在第一步中提到了伪元素 :before:before ,它们可以在CSS中动态生成元素。我们不会当前项目中使用它。不过在通配符选择器中使用伪元素是很常用的做法。

演示源代码

这是练习的源代码。 点击下载

总结

休息一下我们再继续。

将盒子模型所有内容学完并不容易。这些概念虽然只是简单介绍,却花了很多时间来掌握它。

这节课所学内容概括如下:

  • 元素是如何显示的

  • 什么是盒子模型,它为什么很重要

  • 怎么修改元素的大小,包括宽度和高度

  • 怎么添加元素的外边距,内边距和边框

  • 怎么修改元素box-sizing及其对盒子模型的影响

现在我们对如何显示元素和设置尺寸有了更好的了解,接下来我们深入了解一下元素的定位。