CSS 单位系统:尺寸的语言艺术
单位的本质
在 CSS 中,几乎所有的尺寸和距离都需要单位。选择正确的单位不仅影响页面的视觉效果,更决定了网站的响应式能力和可维护性。
CSS 单位可以分为两大类:
- 绝对单位:固定不变的物理尺寸
- 相对单位:相对于其他元素或上下文的尺寸
理解每种单位的特性和适用场景,是掌握 CSS 布局的关键。
绝对单位
绝对单位的大小是固定的,不会随上下文改变。
px(像素)
像素是最常用的绝对单位,代表屏幕上的一个物理像素点:
css
.box {
width: 200px;
height: 100px;
font-size: 16px;
border: 1px solid #ddd;
}特点:
- 精确控制尺寸
- 在不同设备上保持相同的视觉大小(在相同的设备像素比下)
- 不受父元素影响
适用场景:
- 边框宽度:
border: 1px solid #ddd - 阴影偏移:
box-shadow: 2px 4px 8px rgba(0,0,0,0.1) - 小图标尺寸:
width: 24px; height: 24px - 媒体查询断点:
@media (min-width: 768px)
注意事项:
css
/* 现代设备的像素密度问题 */
/* iPhone 的物理分辨率是 750x1334,但 CSS 像素是 375x667 */
/* 这是因为设备像素比(Device Pixel Ratio, DPR)为 2 */
.icon {
width: 20px; /* 在高DPI屏幕上实际占用 40 个物理像素 */
}
/* 移动端适配 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.retina-image {
background-image: url("[email protected]");
background-size: 100px 100px; /* 原始尺寸的一半 */
}
}其他绝对单位
这些单位主要用于打印样式:
css
/* 很少在屏幕显示中使用 */
.print-content {
width: 21cm; /* 厘米 */
height: 29.7cm; /* A4 纸的尺寸 */
margin: 2.54cm; /* 1英寸 = 2.54cm */
font-size: 12pt; /* 点,1pt = 1/72英寸 */
line-height: 1pc; /* 派卡,1pc = 12pt */
}
@media print {
body {
width: 210mm; /* 毫米 */
margin: 1in; /* 英寸 */
}
h1 {
font-size: 18pt; /* 打印时使用 pt 更精确 */
}
}相对单位
相对单位的大小取决于其他元素或上下文,这使得它们特别适合响应式设计。
em - 相对于父元素
em 相对于当前元素的 font-size,如果当前元素未设置 font-size,则相对于父元素的 font-size:
css
/* 基础示例 */
.parent {
font-size: 16px;
}
.child {
font-size: 1.5em; /* 16px × 1.5 = 24px */
padding: 1em; /* 24px × 1 = 24px(相对于自己的font-size) */
margin: 0.5em; /* 24px × 0.5 = 12px */
}
/* em 的复合效应 */
.level-1 {
font-size: 1.2em; /* 假设父元素是 16px,这里是 19.2px */
}
.level-1 .level-2 {
font-size: 1.2em; /* 19.2px × 1.2 = 23.04px */
}
.level-1 .level-2 .level-3 {
font-size: 1.2em; /* 23.04px × 1.2 = 27.65px */
}
/* 嵌套会导致字体越来越大或越来越小 */实际应用:
css
/* 创建模块化的组件 */
.button {
font-size: 16px; /* 基准大小 */
padding: 0.5em 1em; /* 8px 16px */
border-radius: 0.25em; /* 4px */
margin: 0.5em; /* 8px */
}
.button-large {
font-size: 20px; /* 改变基准 */
/* padding 自动变为 10px 20px */
/* border-radius 自动变为 5px */
/* margin 自动变为 10px */
}
.button-small {
font-size: 12px;
/* 所有尺寸按比例缩小 */
}
/* 响应式排版 */
h1 {
font-size: 2em; /* 相对于父元素 */
margin-bottom: 0.5em; /* 保持比例 */
line-height: 1.2em; /* 相对于自己 */
}rem - 相对于根元素
rem(root em)相对于根元素(<html>)的 font-size,避免了 em 的复合效应:
css
/* 设置根元素基准 */
html {
font-size: 16px; /* 1rem = 16px */
}
.container {
padding: 1rem; /* 16px */
margin-bottom: 2rem; /* 32px */
}
.title {
font-size: 2rem; /* 32px */
margin-bottom: 1rem; /* 16px */
}
.nested .deeply .buried .text {
font-size: 1rem; /* 始终是 16px,不受嵌套影响 */
}响应式设计:
css
/* 基于根字体大小的响应式系统 */
html {
font-size: 16px;
}
@media (max-width: 768px) {
html {
font-size: 14px; /* 所有使用 rem 的元素自动等比缩小 */
}
}
@media (max-width: 480px) {
html {
font-size: 12px;
}
}
/* 所有尺寸都会自动适配 */
.card {
padding: 1.5rem; /* 平板: 21px, 手机: 18px */
border-radius: 0.5rem; /* 平板: 7px, 手机: 6px */
}
.heading {
font-size: 2.5rem; /* 平板: 35px, 手机: 30px */
margin-bottom: 1rem; /* 平板: 14px, 手机: 12px */
}使用技巧:62.5% 基准:
css
/* 方便计算的技巧 */
html {
font-size: 62.5%; /* 16px × 62.5% = 10px */
}
body {
font-size: 1.6rem; /* 16px */
}
.text-small {
font-size: 1.2rem; /* 12px */
}
.text-large {
font-size: 2rem; /* 20px */
}
.heading {
font-size: 3.2rem; /* 32px */
}% - 百分比
百分比单位相对于父元素的对应属性值:
css
/* 宽度百分比 */
.container {
width: 100%; /* 父元素宽度的 100% */
max-width: 1200px; /* 限制最大宽度 */
}
.column {
width: 50%; /* 父元素宽度的 50% */
padding: 2%; /* 父元素宽度的 2% */
}
/* 高度百分比 - 需要父元素有明确高度 */
.parent {
height: 500px; /* 必须设置高度 */
}
.child {
height: 80%; /* 500px × 80% = 400px */
}
/* padding 和 margin 的百分比都相对于父元素的宽度 */
.box {
width: 100%;
padding-bottom: 56.25%; /* 16:9 宽高比 (9/16 = 0.5625) */
}
/* position 定位中的百分比 */
.centered {
position: absolute;
top: 50%; /* 相对于父元素高度 */
left: 50%; /* 相对于父元素宽度 */
transform: translate(-50%, -50%); /* 相对于自身尺寸 */
}
/* transform 中的百分比相对于元素自身 */
.slide-in {
transform: translateX(-100%); /* 向左移动自身宽度 */
}
/* background-position 的百分比 */
.banner {
background-position: 50% 50%; /* 水平和垂直居中 */
}视口单位
视口单位相对于浏览器视口(viewport)的尺寸。
vw 和 vh
css
/* vw: 1vw = 视口宽度的 1% */
/* vh: 1vh = 视口高度的 1% */
/* 全屏区块 */
.hero {
width: 100vw; /* 视口宽度的 100% */
height: 100vh; /* 视口高度的 100% */
}
/* 响应式文字 */
.title {
font-size: 5vw; /* 在 1200px 宽的屏幕上是 60px */
/* 在 375px 宽的手机上是 18.75px */
}
/* 限制范围 */
.responsive-text {
font-size: clamp(16px, 4vw, 48px);
/* 最小 16px,理想 4vw,最大 48px */
}
/* 固定宽高比的容器 */
.video-container {
width: 80vw;
height: 45vw; /* 16:9 比例 (80 × 9/16 = 45) */
max-width: 1200px;
max-height: 675px;
}vmin 和 vmax
css
/* vmin: 视口宽度和高度中较小的值的 1% */
/* vmax: 视口宽度和高度中较大的值的 1% */
/* 在任何方向都能看到的元素 */
.square {
width: 50vmin; /* 始终不超过视口的一半 */
height: 50vmin;
}
/* 响应式图标 */
.icon {
font-size: 10vmin; /* 横屏和竖屏都保持合适大小 */
}
/* 全屏背景 */
.background {
width: 100vmax;
height: 100vmax;
}lvh, svh, dvh - 移动端视口单位
CSS 新增的视口单位,解决移动端地址栏问题:
css
/* lvh (Large Viewport Height): 不包含地址栏的高度 */
/* svh (Small Viewport Height): 包含地址栏的高度 */
/* dvh (Dynamic Viewport Height): 动态高度 */
.mobile-hero {
height: 100dvh; /* 动态适应地址栏的显示/隐藏 */
}
.fixed-header {
height: 100svh; /* 使用最小视口高度 */
}
.content {
min-height: 100lvh; /* 使用最大视口高度 */
}角度单位
用于 transform 和 gradient:
css
.rotated {
transform: rotate(45deg); /* 度 (0-360) */
transform: rotate(0.785rad); /* 弧度 */
transform: rotate(50grad); /* 百分度 (0-400) */
transform: rotate(0.125turn); /* 圈数 */
}
.gradient {
background: linear-gradient(135deg, blue, red);
}时间单位
用于动画和过渡:
css
.transition {
transition: all 0.3s ease; /* 秒 */
transition: all 300ms ease; /* 毫秒 */
}
.animation {
animation: slide 2s ease-in-out; /* 2秒 */
animation-delay: 500ms; /* 延迟 500毫秒 */
}calc() 函数
混合使用不同单位:
css
/* 基本计算 */
.container {
width: calc(100% - 80px); /* 百分比减去固定值 */
padding: calc(2rem + 10px); /* rem 加上 px */
margin: calc(5vw - 20px); /* 视口单位减 px */
}
/* 复杂布局 */
.sidebar {
width: 300px;
}
.main-content {
width: calc(100% - 300px); /* 剩余宽度 */
}
/* 响应式间距 */
.grid {
grid-template-columns: repeat(3, calc((100% - 40px) / 3));
gap: 20px;
}
/* 动态字体大小 */
.fluid-text {
font-size: calc(16px + 1vw); /* 基础大小 + 视口缩放 */
}
/* 嵌套 calc */
.complex {
width: calc(100% - calc(20px * 2));
}实战技巧
响应式排版系统
css
:root {
--base-size: 16px;
--scale-ratio: 1.25;
--text-xs: calc(var(--base-size) / var(--scale-ratio) / var(--scale-ratio));
--text-sm: calc(var(--base-size) / var(--scale-ratio));
--text-base: var(--base-size);
--text-lg: calc(var(--base-size) * var(--scale-ratio));
--text-xl: calc(var(--base-size) * var(--scale-ratio) * var(--scale-ratio));
--text-2xl: calc(
var(--base-size) * var(--scale-ratio) * var(--scale-ratio) * var(--scale-ratio)
);
}
.text-xs {
font-size: var(--text-xs);
} /* ~10px */
.text-sm {
font-size: var(--text-sm);
} /* ~13px */
.text-base {
font-size: var(--text-base);
} /* 16px */
.text-lg {
font-size: var(--text-lg);
} /* ~20px */
.text-xl {
font-size: var(--text-xl);
} /* ~25px */
.text-2xl {
font-size: var(--text-2xl);
} /* ~31px */完美的正方形
css
/* 使用 padding-bottom 创建正方形 */
.square {
width: 100%;
padding-bottom: 100%; /* 相对于宽度 */
position: relative;
background: blue;
}
.square-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* 使用 aspect-ratio(现代浏览器) */
.modern-square {
width: 100%;
aspect-ratio: 1 / 1;
}
.video-16-9 {
width: 100%;
aspect-ratio: 16 / 9;
}流式排版
css
/* 使用 clamp 实现流式文字大小 */
h1 {
font-size: clamp(2rem, 5vw, 4rem);
/* 最小 2rem, 理想 5vw, 最大 4rem */
}
p {
font-size: clamp(1rem, 1vw + 0.5rem, 1.5rem);
}
/* 流式间距 */
.section {
padding: clamp(2rem, 5vw, 5rem) clamp(1rem, 3vw, 3rem);
}容器查询单位(实验性)
css
/* 基于容器的单位 */
.card {
container-type: inline-size;
}
.card-title {
font-size: 5cqw; /* Container Query Width */
}
.card-content {
padding: 2cqh; /* Container Query Height */
}单位选择指南
| 用途 | 推荐单位 | 原因 |
|---|---|---|
| 字体大小 | rem | 全局一致性,易于响应式 |
| 内外边距(小) | px | 精确控制细节 |
| 内外边距(大) | rem | 保持整体比例 |
| 宽度 | %, vw, fr | 响应式布局 |
| 最大宽度 | px, rem | 限制极值 |
| 边框 | px | 精确到像素 |
| 阴影 | px | 精确控制 |
| 行高 | 无单位数字 | 相对于字体大小的倍数 |
| 媒体查询 | em, px | 一致的断点 |
| 动画 | s, ms | 时间控制 |
总结
选择合适的 CSS 单位是构建响应式、可维护网站的基础。没有绝对最好的单位,关键是理解每种单位的特性,根据具体场景做出明智的选择。
核心要点:
- 绝对单位:固定大小,不受上下文影响
px- 最常用,精确控制- 打印单位(cm, mm, in, pt, pc)- 主要用于打印样式
- 相对单位:大小相对于其他元素或上下文
em- 相对于父元素,有复合效应rem- 相对于根元素,无复合效应,推荐用于全局%- 相对于父元素对应属性
- 视口单位:相对于浏览器视口
vw,vh- 视口宽度和高度vmin,vmax- 视口的最小/最大值lvh,svh,dvh- 移动端视口单位
- 其他单位:角度(deg, rad)、时间(s, ms)
- calc() 函数:混合使用不同单位进行计算
- 实战技巧:响应式排版、完美正方形、流式排版、容器查询
- 选择指南:根据用途选择最合适的单位