头图

盒子

当对一个文档进行布局的时候,浏览器渲染引擎会根据标准,将页面中的所有元素表示为一个一个矩形的盒子。CSS决定这些盒子的大小、位置以及属性。每个盒子有四个部分组成,分别是:content,padding,border,margin。
盒模型

属性解释:

  1. content内容区域,内容区域可以定义widthheight
  2. padding内容区域和边框之间的空间量
  3. border内容区域和内边距周围边框的粗细和样式。
  4. margin边框和元素外边缘的空间量

块级盒子和内联盒子

在CSS中我们广泛的使用两种『盒子』——块级盒子和内联盒子。两种盒子在页面布局中有以下特点:

块级盒子

  • 盒子会换行显示
  • widthheight属性可以发挥作用
  • 内边距padding外边距margin边框border会将其他元素从当前盒子周围推开
  • 默认情况下盒子宽度会跟父容器一样宽

内联盒子

  • 盒子不会换行
  • widthheight属性不起作用
  • 垂直方向的内边距、外边距以及边框会被应用,但是不会把其它处于inline状态的盒子推开。
  • 水平方向的内边距、外边距以及边框会被应用,并且会把其它处于inline状态的盒子推开。

我们通过对盒子display属性的设置,来控制盒子的外部显示类型。

盒模型类型

完整的CSS盒模型应用于块级盒子,内联盒子只使用盒模型中定义的部分内容。盒模型有两种类型,标准盒模型和IE盒模型。

标准盒模型

在标准盒模型中,如果给盒子设置widthheight,实际设置的是content内容区域的宽和高。内边距padding和边框border加上设置的宽高一起决定了盒子的大小。

IE盒模型

在IE盒模型中,如果给盒子设置widthheight,那么盒子的大小就是设置的宽高值,如果盒子设置了内边距padding和边框border,那么内容的大小实际上是盒子的大小减去内边距和边框的大小之后的值。

差异比较

假设我们定义了如下一个盒子

.box {
    width:100px;
    height:100px;
    margin:25px;
    padding:20px;
    border:15px solid #000;
}

标准盒模型盒子图示:

标准盒模型

盒子的宽度=width + padding-left + padding-right + border-left + border-right(100+20+20+15+15 = 170)

内容的宽度 = width(100)

IE盒模型图示:

IE盒模型

盒子的宽度=width(100)

内容的宽度 = width - padding-left - padding-right - border-left - border-right(100-20-20-15-15 = 30)

在标准盒模型当中,我们使用CSS定义盒子的宽度width和高度height并不是盒子所占据空间大小。

在IE盒模型当中使用CSS定义盒子的宽度width和高度height就是盒子的大小。

盒模型切换

在现代浏览器当中,几乎所有的浏览器,默认的盒模型都是标准盒模型。如果想要使用IE盒模型,可以通过设置属性box-sizing: border-box来设置。

在早期还是IE浏览器天下的时候,如果HTML文档缺失DOCTYPE文档定义标签,在IE6、IE7、IE8下默认使用的是IE盒模型。

盒模型没有好坏优劣之分,根据情况的差异我们选择不同的盒模型。

折叠边距(边距重叠)

折叠边距(边距重叠)不是一个Bug;之前我们说过BFC,下面是W3C关于BFC的相关说明原文:

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

翻译一下就是说:『在BFC当中,盒子是按照垂直方向一个叠一个排列的,垂直方向上两个盒子的距离是由margin属性决定的,在BFC垂直方向的块级盒子之间margin会发生collapse折叠』

特点

在W3C关于CSS章节的8.3.1章节详细说了Collapsing margins边距折叠的特点,在此我简单总结一下一些(不全),详细的内容点击查看

  • 边距折叠只会发生在垂直方向上,横向margin不会发生折叠
  • 根元素框的边距不会折叠
  • 如果具有间隙的元素的顶部和底部边距相邻,则其边距与后续兄弟元素的相邻边距折叠,但生成的边距不会与父块的底部边距折叠。
  • 当两个或更多边距折叠时,产生的边距宽度是折叠边距宽度的最大值。在负边距的情况下,从正相邻边距的最大值中减去负相邻边距绝对值的最大值。如果没有正边距,则从零中减去相邻边距绝对值的最大值。
发生折叠的情况
  • 同一层相邻元素之间,相邻元素外边距重叠
  • 父元素与子元素外边距重叠
  • 空的块级元素重叠

解决方法

知道了会发生边距折叠的原因,那么解决方法自然是小菜一碟。

  1. 改变文档流,使用float或者position
  2. 触发元素的BFC(创建了BFC的元素和它的子元素不会发生折叠)
  3. 只有块级盒子才会发生折叠,修改元素盒子类型为内联盒子

面试回答

一个完整的盒模型有四部分组成,分别是内容区域content,内边距padding,边框border,以及外边距margin;其中margin不参与计算盒子的大小;盒模型有两种类型,IE盒模型和标准盒模型;有时候IE盒模型也被成为怪异盒模型;在现代浏览器当中默认是盒子模型,我们可以通过CSS的box-sizing:border-box;来修改盒模型为IE盒模型;在IE盒模型当中,盒子的宽度是我们定义的width值,而在标准盒模型当中盒子的宽度是内容的width值加上左右内边距加上左右边框的值。

扩展阅读

详解CSS的盒模型(box model) 及 CSS3新增盒模型计算方式box-sizing

Collapsing margins

BFC


前端面试系列其它文章

前端面试CSS系列——BFC
前端面试CSS系列——DIV垂直水平居中
前端面试CSS系列——移动端1PX像素问题


mmcai
126 声望10 粉丝

勿忘初心,方得始终