CSS盒状模型(box model),可以说是很多前端入行人员的必备课程。只有经历了这里面的坑,才可能成为一名合格的前端开发人员。


那么什么是CSS盒状模型呢?


在HTML文档中,一个元素通常用一个矩形来表示,这个矩形在CSS中的标准称呼就是盒状模型,它由五部分组成:外边距(margin)、边框(border)、内边距(padding)和内容部分(content),以及绝对被很多很多文章所忽略的box-sizing属性。


本文不想走别人的套路——一上来就介绍前四部分,那条路还是留给更多的人走吧;本文想从小路入手,先介绍box-sizing,最后走到大路上,但绝对会让你看到另类的风景,好风景总是在无人问津处。


1. box-sizing属性

box-sizing属性是CSS盒状模型的纲,提住纲就等于把握住了CSS布局的走向。在这方面,box-sizing可以说是对盒状模型的重新定义!什么?没听错吧?重新定义?对的。我们一直以为我们所熟悉盒状模型,只不过是默认的一种box-model,仅仅是一种而已。box-sizing属性的使命,就是用于更改我们所熟知的默认的box-model的。它提供了三种值,分别是:content-boxborder-boxinherit。如果你想恢复成默认值,可以使用initial这个关键字。另外,inherit也是一个关键字,表示和父元素一样(一看就是没出息的样子但有时候又很有用)。以下重点介绍content-box和border-box。


2. content-box下的盒状模型

这是默认的box-model模型,也是很多介绍box-model的标准入口,现在我们从小路回到大路上,来看看成为标准的盒装模型的前四部分:margin、padding、border、content-size。废话不多说,请看下图:

content-box模型

在这个图中,margin是盒子的外部区域,用来排空其他外部元素的,表示这是我的地盘儿,你们其他元素别进来。border部分可以表示为边框线,就像我们的长城,实打实的一条线。而padding则表示对内的排空区,表示内部的元素不要进来,剩下的里面的就是content区域了。


在content-box模型中,宽和高指的是content的宽和高,在计算一个盒子实际占据的面积时,还要考虑margin、border和padding区域。为了让大家更清晰一些,我们用数学的语言描述一下:


最后,对于上面的图形,我们落实到代码上看看,可以用类似如下的代码表示:

<style>

   #sample {
      margin: 20px;
      border: 10px solid rgb(202, 223, 184);
      padding: 40px;
      background: rgb(229, 240, 219);
      width: 350px;
      height: 150px;
   }
   #sample .content {
      width: 100%;
      height: 100%;
      background: rgb(94,129,64);
      color: white;
      /* 忽略以下两行,仅仅为了让文字居中 */
      line-height: 150px;
      text-align: center;
   }
</style>
<div id="sample">
   <div class="content">
      内容区域
   </div>
</div>


那上面那段代码占了多的空间呢?宽为20 + 10 + 40 + 350 + 40 + 10 + 20 = 490px,高为20 + 10 + 40 + 150 + 40 + 10 + 20= 290px。


3. border-box下的盒状模型

这个盒状模型和conent-box相比,改变了高和宽的定义,border-box定义的高和宽是从边界开始的,在计算盒子占据的面积时将不再考虑border和padding,如下图:

border-box盒状模型

对于border-box定义下的盒状模型,计算盒子所占据的领地就轻松的多了:

同样,实现代码如下,只需多加一行即可:

<style>
   #sample {
      margin: 20px;

      border: 10px solid rgb(202, 223, 184);
      padding: 40px;
      background: rgb(229, 240, 219);
      width: 350px;
      height: 150px;
      box-sizing: border-box;
   }
   #sample .content {
      width: 100%;
      height: 100%;
      background: rgb(94,129,64);
      color: white;
      /* 忽略以下两行,仅仅为了让文字居中 */
      line-height: 150px;
      text-align: center;
   }
</style>
<div id="sample">
   <div class="content">
      内容区域
   </div>
</div>


那它占据了多大的面积呢?很遗憾,宽仅390px,高190px;和content-box相比,缩水了不少。


通过对比两个盒状模型,你发现了什么没有?是不是发现有些以前很难处理的布局问题可以在border-box这么模型中找到答案?


4. box-model不得不说的坑

不经历风雨,怎能见彩虹?作为前端开发人员,不经过几个坑,那不能称作前端。下面就说说里面的坑,不为别的,只为你跳进坑里的时候能够快点儿爬出来。

4.1 关于margin合并

说到margin合并,是指多个元素可以共用的margin区域,只要别的元素border不进入我的margin区域,就可以相安无事。但在HTML文档的元素丛林中,还得有丛林法则,那就是每个元素都试图占据更大的地盘儿,所以能共用的区域就最大化的利用起来,那最后的结果就是尽可能的重叠margin区域。如下图所示,图中棕色部分就是被重叠复用的margin区域。


4.2 无法穿越padding的margin

划好了边界线(border),或者规定了对内的排空区(padding),那里面元素的margin区域就属于内部元素之间的地盘争夺战了,内部怎么斗也不能把战火烧到外面去,连排空区域都不允许进入,于是内部元素的margin被牢牢的限制在了内容区域。

但如果父元素某个边没指定border或padding,那里面的元素就不会那么安生,它的margin立刻冲出牢笼,对外宣布那是它的地盘儿,于是就有了下图:




(上图)



4.3 百分比问题



4.4 负margin问题


最后,学好、学透CSS盒状模型,达到灵活运用的境界,在布局上可以说能独步武林,但仍需再加一本心法秘籍flex便可称霸天下了。我们下回分解。