盒子大小

Avatar of Marie Mosley
Marie Mosley

DigitalOcean 提供适合您旅程各个阶段的云产品。 立即开始使用 价值 200 美元的免费积分!

box-sizing 属性可以使构建 CSS 布局变得更容易,也更直观。 它对开发人员来说太有帮助了,以至于我们在 CSS-Tricks 每年 2 月都会 庆祝国际盒子大小意识日

但是,为什么它如此有用且受欢迎,以至于拥有自己的网络节日? 现在让我们来了解一些 CSS 历史。

盒子模型历史

从 CSS 诞生之日起,盒子模型 默认情况下一直是这样工作的

宽度 + 内边距 + 边框 = 元素盒子实际可见/渲染宽度

高度 + 内边距 + 边框 = 元素盒子实际可见/渲染高度

这可能有点违反直觉,因为您为元素设置的宽度和高度,一旦您开始向元素添加内边距和边框,就会失效。

在网页设计早期,Internet Explorer 的早期版本(<= IE6)在“怪异模式”下以不同的方式处理盒子模型。 “怪异”盒子模型的工作方式如下: 宽度 = 元素盒子实际可见/渲染宽度 高度 = 元素盒子实际可见/渲染高度 边框和内边距值被移到元素盒子的内部,缩减盒子的宽度/高度,而不是扩展它。

顶部的盒子显示默认盒子模型。 底部的盒子显示曾经是“怪异模式”下对盒子模型的解释。

有些人更喜欢这种对盒子模型的“怪异”解释,并认为它更直观。 这是一个有效的观点。 拥有与您在 CSS 中声明的不同的盒子实际可见宽度,确实有点令人费解。

但是,在固定宽度设计的时代,一旦您理解了默认盒子模型,它就不是特别复杂。 您可以进行一些算术运算,弄清楚需要从元素的声明宽度或高度中裁剪掉多少像素才能容纳它的内边距和边框。 当今开发人员的问题是,这些绝对像素长度不能转换为响应式设计,因此相同的数学运算不再适用。

随着响应式设计(或曾经被称为“流体”或“液体”布局)开始流行起来,开发人员和设计师希望对盒子模型进行更新。 著名的设计师 Jon Hicks 以其出色的流体宽度设计而闻名,他在我们 2008 年发布的 CSS 愿望清单 中谈到了这个主题

我想要一个不同的盒子模型! 我觉得内边距和边框会增加对象的宽度很奇怪,我真的很想能够为像 textarea 这样的元素设置 100% 宽度和 3px 内边距,而不必担心它会对布局造成什么影响。 也许可以像 padding-inside 这样添加一个新的选择器?

同样,我希望能够为元素指定 100% 宽度,减去一个固定的宽度。 这在使用表单元素创建流体设计时非常有用!

现在的 box-sizing

当 CSS3 中引入 box-sizing 属性时,这些愿望得以实现。 尽管 box-sizing 有三个可能的值(content-boxpadding-boxborder-box),但最常用的值是 border-box

如今,所有浏览器当前版本都使用最初的“宽度或高度 + 内边距 + 边框 = 实际宽度或高度”盒子模型。 借助 box-sizing: border-box;,我们可以将盒子模型更改为曾经的“怪异”方式,即元素的指定宽度和高度不受内边距或边框的影响。 这在响应式设计中被证明非常有用,因此它已成为重置样式的一部分。

此时,您可能在问自己,“难道旧 IE 做了什么正确的事情?” 很多人都这么认为

演示

此演示展示了 border-box 如何帮助使响应式布局更易于管理。 父级 div 的宽度为 50%,它有 3 个子元素,它们具有不同的宽度、内边距和外边距。 点击 border-box 按钮,将所有子元素正确地放置到父元素中。

查看 CodePen 上的 盒子大小布局演示,由 CSS-Tricks (@css-tricks) 创建。

良好、更好以及(可能)最佳的 box-sizing 重置方法

“旧”的 border-box 重置

最早的 box-sizing: border-box; 重置看起来像这样

* {
  box-sizing: border-box;
}

这效果很好,但它忽略了伪元素,这可能会导致一些意想不到的结果。 很快出现了一种改进的重置,它涵盖了伪元素

通用盒子大小

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

此方法也选择了伪元素,提高了 border-box 的规范化效果。 但是,* 选择器使得开发人员很难在其他 CSS 中使用 content-boxpadding-box。 这就引出了目前最佳实践的领先者

带继承的通用盒子大小

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

此重置比它的前辈提供了更多的灵活性——您可以根据需要使用 content-boxpadding-box(在支持的情况下),而无需担心通用选择器会覆盖您的 CSS。 我们在 “继承 box-sizing 可能略好于最佳实践” 中对该技术及其背后的原因进行了更深入的探讨。 它可能的一个缺点是,box-sizing 通常不会被继承,因此它是专门的行为,与您通常放在重置中的内容略有不同。

供应商前缀

所有现代浏览器都支持无前缀的 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;
  }

已知问题

box-sizing: border-box; 在所有主要浏览器当前版本中都受支持。 不常用的 padding-box 目前仅在 Firefox 中受支持。 我们的 box-sizing 年鉴条目中提供了有关浏览器支持的更多全面信息。

旧版 Internet Explorer(8 及更早版本)存在一些问题。IE 8 无法识别带有 `min/max-width` 或 `min/max-height` 属性的元素的 `border-box`(以前 Firefox 也存在此问题,但已在 2012 年修复)。IE 7 及更早版本完全无法识别 `box-sizing`,但有一个 polyfill 可以帮助解决