谈谈盒模型

82 阅读7分钟

什么是盒模型

在 CSS 中,所有的元素都被一个个的盒子(box)包围着,盒模型分为IE盒模型和W3C标准盒模型。

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

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

如下图:

image.png

标准盒模型

标准盒模型由content(内容)、padding(内边距)、border(边框)、margin(外边距)组成。但盒子的大小由content+padding+border这几部分决定,把margin算进去的那是盒子占据的位置,而不是盒子的大小!

在标准模型中,如果你给盒设置 widthheight,此时width和height就是content box的大小,盒子的大小是由content box、padding 、 border 一起决定整个。

比如假设定义了 width, height, margin, border, and padding:

.box {
  width: 350px;
  height: 150px;
  margin: 25px;
  padding: 25px;
  border: 5px solid black;
}

如果使用标准盒模型,盒子宽度 = 410px (350 + 25 + 25 + 5 + 5),盒子高度 = 210px (150 + 25 + 25 + 5 + 5)。

image.png

备注: margin 不计入实际大小 —— 当然,它会影响盒子在页面所占空间,但是影响的是盒子外部空间。盒子的范围到边框为止 —— 不会延伸到 margin。

IE盒模型

使用IE盒模型模型,width宽度即是可见宽度,所以内容宽度是该宽度减去边框和填充部分。

设置box-sizing属性为border-box会发现无论我们怎么改border和padding盒子大小始终是定义的width和height。

比如假设定义了 width, height, margin, border, and padding:

.box {
  width: 350px;
  height: 150px;
  margin: 25px;
  padding: 25px;
  border: 5px solid black;
}

如果使用IE盒模型宽度 = 350px,高度 = 150px。那么盒子的宽度和高度就是350px和150px。content宽度=290px(350-25-25-5-5),content高度=90px(150-25-25-5-5)

image.png

默认浏览器会使用标准盒模型。如果需要使用替代的IE盒模型,您可以通过为其设置 box-sizing: border-box 来实现。

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

如果你希望所有元素都使用替代模式,而且确实很常用,设置 box-sizing<html> 元素上,然后设置所有元素继承该属性,正如下面的例子。

html {
  box-sizing: border-box;
}
*, *::before, *::after {
  box-sizing: inherit;
}

备注: Internet Explorer 默认使用替代盒模型,没有可用的机制来切换。(IE8+ 支持使用 box-sizing 进行切换)

外边距,内边距,边框

外边距

外边距是盒子周围一圈看不到的空间。它会把其他元素从盒子旁边推开。外边距属性值可以为正也可以为负。设置负值会导致和其他内容重叠。无论使用标准模型还是替代模型,外边距总是在计算可见部分后额外添加。

外边距折叠

理解外边距的一个关键是外边距折叠的概念。如果你有两个外边距相接的元素,这些外边距将合并为一个外边距,即最大的单个外边距的大小。

比如我们有两个相邻的段落。顶部段落的页 margin-bottom为 50px。第二段的margin-top 为 30px。因为外边距折叠的概念,所以框之间的实际外边距是 50px,而不是两个外边距的总和。

边框

边框是在边距和填充框之间绘制的。如果您正在使用标准的盒模型,边框的大小将添加到框的宽度和高度。如果您使用的是替代盒模型,那么边框的大小会使内容框更小,因为它会占用一些可用的宽度和高度。

内边距

内边距位于边框和内容区域之间。与外边距不同,不能有负数的内边距,所以值必须是 0 或正的值。应用于元素的任何背景都将显示在内边距后面,内边距通常用于将内容推离边框。

盒模型的显示类型

css 的 box 模型有内部和外部显示类型,外部显示类型决定盒子是块级还是内联,内部显示类型决定盒子内部元素是如何布局的。

内部显示类型

内部显示类型决定盒子内部元素是如何布局的。默认情况下是按照 正常文档流 布局 。可以通过使用 display 属性值来更改内部显示类型。如果在一个元素上设置 display: flex,那么在此元素上,外部显示类型是 block,但是内部该盒子的所有直接子元素都会成为 flex 元素,会根据弹性盒子(Flexbox)规则进行布局。

这里解释下文档流:

在HTML文档中,默认情况下元素的位置根据它前面正常渲染的元素位置进行计算。元素常见类型分为块级元素(block element)、行内元素(inline element)、行内块元素(inline-block element),除了特殊的比如flex规则外,HTML文档将元素根据这些类型从上到下、从左到右地排布,我们把文档将默认元素一一排开的过程形象地想象成一种流体,于是就把这个称之为文档流。

外部显示类型

在 CSS 中我们广泛地使用两种“盒子” —— 块级盒子 (block box) 和 内联盒子 (inline box)。

一个被定义成块级的(block)盒子会表现出以下行为:

  • 盒子会在横向的方向上扩展并占据父容器在该方向上的所有可用空间,意味着盒子会和父容器一样宽
  • 每个盒子都会换行
  • width 和 height属性可以发挥作用
  • 内边距(padding), 外边距(margin)和 边框(border)会将其他元素从当前盒子周围“推开”

一个被定义成内联的(inline)盒子会表现出以下行为:

  • 盒子不会产生换行。
  • width和height属性将不起作用,盒子的大小由其内容决定。
  • 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于 inline 状态的盒子推开。
  • 水平方向的内边距、外边距以及边框会被应用且会把其他处于 inline 状态的盒子推开。

用做链接的 <a> 元素、 <span><em> 以及 <strong> 都是默认处于 inline 状态的。

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

另外display 有一个特殊的值内联块(inline-block),它在内联和块之间提供了一个中间状态。

一个元素使用 display: inline-block,实现我们需要的块级的部分效果:

  • 设置widthheight 属性会生效。
  • padding, margin, 以及border 在垂直和水平方向上都会推开其他元素。

这对于以下情况非常有用:

1,您不希望一个项切换到新行,但希望它可以设定宽度和高度。

2,添加内边距使链接具有更大的命中区域时。<a> 是像 <span> 一样的内联元素,使用 display: inline-block 来设置内边距,让用户更容易点击链接。

总结

我们在编写页面代码时应尽量使用标准的W3C模型(需在页面中声明DOCTYPE类型),这样可以避免多个浏览器对同一页面的不兼容。因为若不声明DOCTYPE类型,IE浏览器会将盒子模型解释为IE盒子模型(针对IE6、7、8),FireFox等会将其解释为W3C盒子模型;若在页面中声明了DOCTYPE类型,所有的浏览器都会把盒模型解释为W3C盒模型。

参考

盒模型