一直在用的标准盒模型和替代(IE)盒模型到底怎么区分的?

4,408 阅读5分钟

从一道面试题讲起:经常在面试过程中面试官会提问,标准盒模型和怪异盒模型的区别是什么?

这里提到的怪异盒模型用官话来讲就是替代盒模型。那到底什么是标准盒模型?什么是替代盒模型呢?我们先来了解一下概念,然后通过一个示例来详细讲解它们的行为和区别。

我们先从浏览器中的盒子开始讲起。

友情提示:如果对盒模型概念已经有认知的可以直接跳到案例讲解部分看实际效果更好。

块级盒子(Block box)和 内联盒子(Inline box)

在 CSS 中,所有的元素都被一个个的“盒子(box)”包围着,在 CSS 中我们广泛地使用两种“盒子” —— 块级盒子 (block box) 和 内联盒子 (inline box)。这两种盒子会在页面流(page flow)和元素之间的关系方面表现出不同的行为。

  1. 一个被定义成块级的(block)盒子会表现出以下行为:
  • 盒子会在内联的方向上扩展并占据父容器在该方向上的所有可用空间,在绝大数情况下意味着盒子会和父容器一样宽
  • 每个盒子都会换行
  • width 和 height 属性可以发挥作用
  • 内边距(padding), 外边距(margin)和 边框(border)会将其他元素从当前盒子周围“推开”
  1. 如果一个盒子对外显示为 inline,那么他的行为如下:
  • 盒子不会产生换行。
  • width 和 height 属性将不起作用。
  • 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于 inline 状态的盒子推开。
  • 水平方向的内边距、外边距以及边框会被应用且会把其他处于 inline 状态的盒子推开。

上面的都是一些官话,大概了解一下盒子模型的行为。正是因为有了这些盒子,我们才能随心所欲的在浏览器中大展身手而不至于超出我们的预期和掌控。

认识了浏览器中的盒子,现在我们来正式认识一下盒模型的概念。

什么是盒子模型?

完整的 CSS 盒模型应用于块级盒子,内联盒子只使用盒模型中定义的部分内容。模型定义了盒的每个部分 —— margin, border, padding, and content —— 合在一起就可以创建我们在页面上看到的内容。为了增加一些额外的复杂性,有一个标准的和替代(IE)的盒模型。

盒模型的各个部分

CSS 中组成一个块级盒子需要:

  • Content box: 这个区域是用来显示内容,大小可以通过设置 widthheight.
  • Padding box: 包围在内容区域外部的空白区域;大小通过 padding 相关属性设置。
  • Border box: 边框盒包裹内容和内边距。大小通过 border 相关属性设置。
  • Margin box: 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过 margin 相关属性设置。

如下图:

标准盒模型

在标准模型中,如果你给盒设置 width 和 height,实际设置的是 content box。padding 和 border 再加上设置的宽高一起决定整个盒子的大小。

替代(IE)盒模型

你可能会认为盒子的大小还要加上边框和内边距,这样很麻烦,而且你的想法是对的 ! 因为这个原因,css 还有一个替代盒模型。使用这个模型,所有宽度都是可见宽度,所以内容宽度是该宽度减去边框和填充部分。使用上面相同的样式得到 (width = 350px, height = 150px).

默认浏览器会使用标准模型。如果需要使用替代模型,您可以通过为其设置 box-sizing: border-box 来实现。这样就可以告诉浏览器使用 border-box 来定义区域,从而设定您想要的大小。

上面的概念介绍也是官话,听着云里雾里的,到底盒模型的宽度是咋个算法嘛,哪个属于哪个嘛?

下面我们以一个实际的案例来展示一下这两种盒模型在浏览器中的表现。

案例讲解

如果你懒得动手,我为你贴心的提供了代码地址,可直接预览和修改:stackblitz.com/edit/web-pl…

<div class="box">I use the standard box model.</div>
<div class="box alternate">I use the alternate box model.</div>
.box {
  border: 5px solid rebeccapurple;
  background-color: lightgray;
  padding: 40px;
  margin: 40px;
  width: 300px;
  height: 150px;
}

.alternate {
  box-sizing: border-box;
}

上面的代码中,有两个div,第一个为标准盒模型,第二个为替代(IE)盒模型。然后分别给他们设置了borderpaddingmarginwidthheight

我们在浏览器中预览一下效果:

可以看到,差距如此之大,这是为什呢?

我们打开浏览器调试工具:

看到这里有个Computed,在这里面可以看到整个盒子的大小。

首先我们看第一个盒子。

我用红框框圈起来的就是用户在界面看到的盒子实际大小。我反手就掏出计算器,我们算一下这个盒子的高度:

h = 5 + 40 + 150 + 40 + 5 = 240

我们本来是设置的盒子高度是150,现在变成240了一下子。这也太让人蛋疼了。而且我们看到最中间内容区域高度它就是150,设置了padding和border以后,把这个盒子给撑大了,变得难以捉摸了。

那我们再来看看第二个盒子。

我用红框框圈起来的也是用户在界面看到的盒子实际大小,我们再掏出计算器算一下:

h = 5 + 40 + 60 + 40 + 5 = 150

正好等于我们设置的盒子高度150。这个是符合我们的预期的。

中间的内容区域高度变成了60了。由此得出一个结论,设置了150的高度,不管border和padding设置多少,它都不会撑开,而是把内容区域往里面挤。我们设置padding和border的目的不就是这样嘛?

现在你对盒模型的行为有了清晰的认知了没有?在实际写代码的时候你应该能知道在什么情况下用什么模型。已经可以完全把控了。