Skip to content

CSS 盒模型

CSS 中的每一个元素都可以看作一个矩形盒子。盒模型定义了这个盒子由哪些部分组成,以及它们如何影响元素的最终尺寸。理解盒模型是写好 CSS 的基础。

盒模型的组成#

每个盒子由四个区域组成,从内到外依次是:

  1. Content(内容区):显示实际内容的区域,由 widthheight 控制
  2. Padding(内边距):内容区与边框之间的空白区域
  3. Border(边框):包裹内容和内边距的边框
  4. Margin(外边距):盒子与其他元素之间的空白区域
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid #3b82f6;
margin: 30px;
}

这个盒子在页面上占据的实际宽度是多少?答案取决于你使用的盒模型。

标准盒模型 vs 替代盒模型#

标准盒模型(content-box)#

标准盒模型是浏览器的默认行为。widthheight 只定义内容区的尺寸,padding 和 border 会额外增加盒子的总尺寸:

.box {
box-sizing: content-box; /* 默认值 */
width: 200px;
padding: 20px;
border: 5px solid #333;
}
/* 实际宽度 = 200 + 20*2 + 5*2 = 250px */

这种计算方式常常让人困惑——你设置了 width: 200px,但盒子实际占据的宽度却是 250px。

替代盒模型(border-box)#

替代盒模型让 widthheight 定义的是包含 padding 和 border 的总尺寸:

.box {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 5px solid #333;
}
/* 实际宽度 = 200px(padding 和 border 包含在内) */
/* 内容区宽度 = 200 - 20*2 - 5*2 = 150px */

🎯 现代开发中几乎都使用 border-box,因为它更符合直觉。推荐在全局样式中设置:

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

Padding 内边距#

内边距是内容与边框之间的空间。

基本语法#

/* 四个方向相同 */
.box {
padding: 20px;
}
/* 上下 | 左右 */
.box {
padding: 20px 40px;
}
/* 上 | 左右 | 下 */
.box {
padding: 10px 20px 30px;
}
/* 上 | 右 | 下 | 左(顺时针) */
.box {
padding: 10px 20px 30px 40px;
}

单边设置#

.box {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;
}

常见场景#

/* 按钮内边距 */
.button {
padding: 0.5rem 1rem; /* 垂直较小,水平较大 */
}
/* 卡片内边距 */
.card {
padding: 1.5rem;
}
/* 容器内边距 */
.container {
padding-inline: 1rem; /* 只设置水平方向(逻辑属性) */
}

🔶 内边距不能为负值,也不会发生合并。

Border 边框#

边框是 padding 和 margin 之间的线条。

基本语法#

/* 完整写法:宽度 样式 颜色 */
.box {
border: 2px solid #333;
}
/* 分开设置 */
.box {
border-width: 2px;
border-style: solid;
border-color: #333;
}

边框样式#

.solid {
border-style: solid;
} /* 实线 */
.dashed {
border-style: dashed;
} /* 虚线 */
.dotted {
border-style: dotted;
} /* 点线 */
.double {
border-style: double;
} /* 双线 */
.none {
border-style: none;
} /* 无边框 */

单边边框#

.box {
border-top: 3px solid #3b82f6;
border-bottom: 1px solid #e5e7eb;
}
/* 只设置某个属性 */
.box {
border-left-width: 4px;
border-left-color: #ef4444;
}

圆角边框#

/* 四个角相同 */
.box {
border-radius: 8px;
}
/* 左上右上 | 右下左下 */
.box {
border-radius: 8px 0;
}
/* 四个角分别设置 */
.box {
border-radius: 8px 16px 8px 16px;
}
/* 圆形 */
.circle {
border-radius: 50%;
}
/* 药丸形状 */
.pill {
border-radius: 9999px;
}

Margin 外边距#

外边距是盒子与其他元素之间的空间。

基本语法#

与 padding 类似:

.box {
margin: 20px; /* 四边 */
margin: 20px 40px; /* 上下 | 左右 */
margin: 10px 20px 30px; /* 上 | 左右 | 下 */
margin: 10px 20px 30px 40px; /* 上 | 右 | 下 | 左 */
}

负值外边距#

与 padding 不同,margin 可以是负值:

/* 向上拉 */
.overlap {
margin-top: -20px;
}
/* 超出容器 */
.bleed {
margin-left: -1rem;
margin-right: -1rem;
}

水平居中#

.centered {
width: 800px;
margin-left: auto;
margin-right: auto;
}
/* 简写 */
.centered {
width: 800px;
margin-inline: auto;
}

🙋 为什么 margin: auto 能实现水平居中?

浏览器会将剩余的水平空间平均分配给左右 margin。但这只对块级元素设置了明确宽度的情况有效。

外边距合并(Margin Collapsing)#

🔶 这是 CSS 中最容易让人困惑的特性之一。

当两个垂直方向的外边距相遇时,它们会合并成一个,取较大的值:

<div class="box1">Box 1</div>
<div class="box2">Box 2</div>
.box1 {
margin-bottom: 30px;
}
.box2 {
margin-top: 20px;
}
/* 两个盒子之间的间距是 30px,不是 50px */

合并发生的条件

  1. 相邻的兄弟元素
  2. 父元素与第一个/最后一个子元素
  3. 空的块级元素

阻止合并的方法

/* 父元素设置 overflow */
.parent {
overflow: hidden; /* 或 auto */
}
/* 父元素设置 padding 或 border */
.parent {
padding-top: 1px;
}
/* 父元素设置 display: flow-root */
.parent {
display: flow-root;
}
/* 使用 Flexbox 或 Grid */
.parent {
display: flex;
flex-direction: column;
}

盒模型与布局#

Inline vs Block#

盒模型对行内元素和块级元素的影响不同:

/* 块级元素:完整应用盒模型 */
div {
width: 200px; /* 生效 */
height: 100px; /* 生效 */
padding: 20px; /* 生效 */
margin: 20px; /* 生效 */
}
/* 行内元素:部分应用 */
span {
width: 200px; /* 无效 */
height: 100px; /* 无效 */
padding: 20px; /* 水平生效,垂直只增加背景区域,不影响布局 */
margin: 20px; /* 只有水平方向生效 */
}

如果需要行内元素应用完整盒模型:

span {
display: inline-block;
}

计算元素尺寸#

了解盒模型后,你可以准确计算元素的各种尺寸:

.box {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
margin: 10px;
}

实战案例#

卡片组件#

.card {
box-sizing: border-box;
width: 100%;
max-width: 400px;
padding: 1.5rem;
border: 1px solid #e5e7eb;
border-radius: 12px;
margin: 0 auto;
}
.card-header {
padding-bottom: 1rem;
border-bottom: 1px solid #e5e7eb;
margin-bottom: 1rem;
}
.card-title {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
}
.card-body {
color: #6b7280;
line-height: 1.6;
}
.card-footer {
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
margin-top: 1rem;
}

间距系统#

使用一致的间距可以让页面看起来更协调:

:root {
--spacing-xs: 0.25rem; /* 4px */
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
--spacing-xl: 2rem; /* 32px */
}
.section {
padding: var(--spacing-xl);
margin-bottom: var(--spacing-lg);
}
.button {
padding: var(--spacing-sm) var(--spacing-md);
}
.input {
padding: var(--spacing-sm);
margin-bottom: var(--spacing-md);
}

全屏布局#

html,
body {
margin: 0;
padding: 0;
height: 100%;
}
.app {
min-height: 100%;
display: flex;
flex-direction: column;
}
.header {
padding: 1rem 2rem;
border-bottom: 1px solid #e5e7eb;
}
.main {
flex: 1;
padding: 2rem;
}
.footer {
padding: 1rem 2rem;
border-top: 1px solid #e5e7eb;
}

调试技巧#

浏览器开发者工具提供了可视化的盒模型查看器:

  1. 右键点击元素 → 检查
  2. 在 Styles 面板中找到盒模型图示
  3. 悬停在不同区域可以在页面上高亮对应部分

临时添加边框也是常用的调试方法:

/* 调试时临时添加 */
* {
outline: 1px solid red !important;
}

🎯 使用 outline 而不是 border,因为 outline 不占用空间,不会影响布局。


盒模型是 CSS 布局的基石。记住使用 box-sizing: border-box 简化尺寸计算,理解外边距合并可以避免很多布局问题。下一篇我们将学习 CSS 定位,掌握元素的精确定位方式。