CSS盒子模型Box Sizing

box-sizing属性可以使构建CSS布局更加容易并且更加直观。对于开发人员而言,这是一个很大的福音,可以避免很多兼容性问题。

Box Model历史

自CSS诞生以来,默认情况下,box模型的工作方式如下:

width + padding + border = element's box 实际可见/渲染宽度

height + padding + border = element's box 实际可见/渲染高度

这有点违背直接,特别是对于设置100%宽度的box来说,增加border和padding宽度,会导致box的实际效果跳出可视范围。

早在Web设计的早期,Internet Explorer的早期版本(<= IE6)在“怪癖模式”下对盒模型的处理方式有所不同。“怪癖”盒子模型的工作方式如下:width = 元素盒子实际的可见/渲染高度;height =元素盒子实际的可见/渲染高度边框和填充值在元素盒子内部移动,切成width / height而不是扩展它。

在web设计的早期,早期版本的Internet Explorer (<= IE6)在“怪癖模式”下处理box模型的方式是不同的。“怪癖”框模型是这样的:工作宽度=实际可见的元素的盒子高度/宽度呈现=实际可见/呈现元素的盒子边界和填充高度值元素的盒子里面,切到盒子的宽度/高度而不是扩张。

如上图所示,顶部的框显示默认的框模型,底部的框显示的怪异模式。

有人更喜欢这种盒模型的“古怪”解释,并认为它更直观。这是有道理的。框的实际可见宽度与您在CSS中声明的宽度不同,这有点令人费解。

但是,在固定宽度设计时代,一旦了解了默认框模型,使用它并不是特别复杂。您可以进行一些算术运算,以找出需要减少多少个像素才能声明元素的声明宽度或高度,以容纳其填充和边框。对于当今的开发人员而言,问题在于这些绝对像素长度不会转换为响应式设计,因此相同的数学不再适用。

随着响应式设计(或以前称为“流体”或“液体”布局)开始流行,开发人员和设计人员希望对盒装模型进行更新。伟大的设计师[Jon Hicks]以出色的流体宽度设计而闻名,他在我们于2008年汇总的CSS Wishlist中谈到了这一点:

我希望使用其他盒子型号!我觉得奇怪的是,填充和边框增加了对象的宽度,并且希望能够为诸如textarea之类的东西提供100%的宽度和3px的填充,而不必担心它会做什么布局。也许像padding-inside这样的新选择器呢?

同样,我也希望我可以为元素指定100%的宽度,减去设置的固定宽度。同样,在使用表单元素创建流畅的设计时非常有用!

当前的box-sizing

当box-sizing在CSS3中引入该属性时,这些愿望得到了满足。尽管box-sizing具有三个值(content-boxpadding-boxborder-box),但最受欢迎的值为border-box

今天,所有浏览器的当前版本都使用原始的“宽度或高度+填充+边框=实际宽度或高度”框模型。使用box-sizing: border-box;,我们可以将box模型更改为以前的“古怪”方式,其中元素的指定宽度和高度不受填充或边框的影响。事实证明,这在响应式设计中非常有用,甚至可以应用到重置样式中。

在这一点上,你可能会问自己,“有可能老IE做了正确的事吗?”很多人都这么认为。

Demo

这个Demo演示了border-box如何使响应式布局更易于管理。父div的宽度为50%,它有3个不同宽度、填充和空白的子div。单击border-box按钮,将所有子元素放到父元素中的正确位置。

box-sizing 重置的最佳方法

旧的 border-box 重置

早起的box-sizing: border-box;重置

* {
    box-sizing: border-box;
}

这可以很好地工作,但是会保留伪元素,这可能会导致一些意外的结果。很快出现了涵盖伪元素的修订后的重置。

通用 Box Sizing
*, *:before, *:after {
    box-sizing: border-box;
}

此方法还选择了伪元素,从而提高了border-box的统一效果。但是,`*`选择器使开发人员在其他地方难以使用CSS `content-box`或`padding-box`。

具有继承的Box Sizing
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

与以前的版本相比,此重置为您提供了更大的灵活性-您可以随意使用content-box或padding-box(如果支持),而不必担心通用选择器会覆盖CSS。

浏览器兼容

当前的每个浏览器都支持box-sizing: border-box;无前缀的,因此对供应商前缀的需求正在减少。但是,如果您需要支持Safari(<5.1),Chrome(<10)和Firefox(<29)的旧版本,则应包括前缀-webkit和-moz,如下所示:

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