重修 CSS(三):盒模型之宽度问题
盒模型是 CSS 中连我都有点了解的基础。在矩形元素内容的外围有三层东西:外边距 margin
、边框 border
、内边距 padding
。
今天的内容来自书中第一部分《基础回顾》的第三章《盒模型》,我们将深入了解盒模型的应用,实现一个两列布局的网页。
宽度问题
假设我们想做一个两列布局的网页,左边是 70% 宽的主栏 main
,右边是 30% 宽的侧边栏。我们可以写出如下的 CSS:
body {
background-color: #eee;
font-family: Helvetica, Arial, sans-serif;
}
header {
color: #fff;
background-color: #0072b0;
border-radius: .5em;
}
main {
display: block; // ie bug fix
}
.main {
float: left;
width: 70%;
background-color: #fff;
border-radius: .5em;
}
.sidebar {
float: left;
width: 30%;
padding: 1.5em;
background-color: #fff;
border-radius: .5em;
}
但是这段 CSS 使得侧边栏跑到了第二行去,因为一个 70% 宽的元素和一个 30% 宽的元素加起来宽度却超过了 100%。
出现这样的错误的原因是 .sidebar
的内边距加大了它的宽度,使得总宽度超出了 3em
。
如何解决这样的问题?一种方法是减少 .sidebar
的宽度,比如改成 26%
。但这种方式显然不解决问题,在某些情况下仍然可能翻车。另一种方式是用 calc
计算宽度,比如 calc(30% - 3em)
,但也并不优雅。
最好的解决方式是调整盒模型。在默认的盒模型 content-box
中,元素的高和宽指的是 margin 内圈的高和宽。因此,padding
和 border
的宽度都将额外增加元素的尺寸。我们可以将 box-sizing
属性设为 border-box
,此时元素的高和宽指的是 border 外圈的高和宽,就避免了计算 border
和 padding
占用屏幕的空间。
给 .main
和 .sidebar
都加上 box-sizing: border-box;
之后,问题得到了解决:
由于 border-box
比 content-box
有用的多,我们可以将默认值设为 border-box
:
*,
::before,
::after {
box-sizing: border-box;
}
这种方式将把所有元素都改为 border-box
。但是当我们使用一些使用 content-box
的第三方组建的时候,就无法将它们的 box-sizing
改回 content-box
。一种解决方案是采用如下的代码:
:root {
box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: inherit;
}
.third-party-component {
box-sizing: content-box;
}
由于层叠可以覆盖继承,这样就可以保留某些元素的 content-box
了。
此时 .main
和 .sidebar
还是紧贴在一起,我们可以用 margin-left: 1.5em;
将它们分开。但是由于 margin
是在宽度之外的,所以我们不得不用 calc()
来重新计算 .sidebar
的宽度:width: calc(30% - 1.5em);
。
这样我们就得到了想要的两列布局:
未完待续
下一篇笔记将会讨论盒模型中的高度问题。