CSS 中的每一个元素都可以看作一个矩形盒子。盒模型定义了这个盒子由哪些部分组成,以及它们如何影响元素的最终尺寸。理解盒模型是写好 CSS 的基础。
盒模型的组成#
每个盒子由四个区域组成,从内到外依次是:
- Content(内容区):显示实际内容的区域,由
width和height控制 - Padding(内边距):内容区与边框之间的空白区域
- Border(边框):包裹内容和内边距的边框
- Margin(外边距):盒子与其他元素之间的空白区域
.box { width: 200px; height: 100px; padding: 20px; border: 5px solid #3b82f6; margin: 30px;}这个盒子在页面上占据的实际宽度是多少?答案取决于你使用的盒模型。
标准盒模型 vs 替代盒模型#
标准盒模型(content-box)#
标准盒模型是浏览器的默认行为。width 和 height 只定义内容区的尺寸,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)#
替代盒模型让 width 和 height 定义的是包含 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 */合并发生的条件:
- 相邻的兄弟元素
- 父元素与第一个/最后一个子元素
- 空的块级元素
阻止合并的方法:
/* 父元素设置 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;}- 总占用宽度(包含 margin):300 + 10×2 = 320px
- 可见宽度(border-box):300px
- 内容区宽度:300 - 20×2 - 2×2 = 256px
实战案例#
卡片组件#
.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;}调试技巧#
浏览器开发者工具提供了可视化的盒模型查看器:
- 右键点击元素 → 检查
- 在 Styles 面板中找到盒模型图示
- 悬停在不同区域可以在页面上高亮对应部分
临时添加边框也是常用的调试方法:
/* 调试时临时添加 */* { outline: 1px solid red !important;}🎯 使用 outline 而不是 border,因为 outline 不占用空间,不会影响布局。
盒模型是 CSS 布局的基石。记住使用 box-sizing: border-box 简化尺寸计算,理解外边距合并可以避免很多布局问题。下一篇我们将学习 CSS 定位,掌握元素的精确定位方式。