大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
单位与函数
这一课你将能做到
- 区分绝对单位和相对单位,知道各自适用场景
- 熟练使用 px、em、rem、%、vw、vh 六大常用单位
- 用 calc()、min()、max()、clamp()、var() 写出灵活的响应式样式
为什么要学
单位是 CSS 的「量词」。字号写死 px,在小屏手机就太小;写死 %,嵌套几层就失控。搞懂单位,才能写出既精致又自适应的页面。clamp() 和 calc() 是现代响应式的核心武器。
人话:单位就是尺子——px 是毫米刻度精确但死板,% 是相对爸爸的比例,rem 是相对根节点的「全局比例」,vw/vh 是「看屏幕大小给」。
先建立图像
<style>
html { font-size: 16px; }
.px { font-size: 24px; }
.em { font-size: 1.5em; } /* 相对父元素 */
.rem { font-size: 1.5rem; } /* 相对 html 根元素 */
.pct { width: 50%; }
.vw { width: 30vw; background: #ffe4e1; }
</style>
<div style="font-size: 20px;">
<p class="px">24px 绝对</p>
<p class="em">1.5em = 30px(父 20 × 1.5)</p>
<p class="rem">1.5rem = 24px(根 16 × 1.5)</p>
</div>
<div class="pct">宽 50%(父宽一半)</div>
<div class="vw">宽 30vw(屏幕宽 30%)</div>
跟着做
步骤 1:绝对单位——px
px 是最常用的绝对单位,1px 在普通屏幕上等于 1 个物理像素点(高清屏会被缩放)。
.title { font-size: 32px; }
.card { width: 300px; border: 1px solid #ddd; }
什么时候用:边框粗细、图标尺寸、精确控场的场景。
步骤 2:相对单位 em
em 相对当前元素或父元素的字体大小:
.parent { font-size: 20px; }
.child { font-size: 1.5em; } /* = 20 × 1.5 = 30px */
.child { padding: 1em; } /* = 30px(按当前字号算) */
嵌套会滚雪球:1.2em 套三层就是 1.2³ = 1.728 倍,难追踪。
步骤 3:相对单位 rem
rem(root em)只相对 <html> 的字体大小,不会滚雪球:
html { font-size: 16px; } /* 默认值 */
h1 { font-size: 2rem; } /* 32px */
p { font-size: 1rem; } /* 16px */
.small { font-size: 0.875rem; } /* 14px */
工程实践:把 html 设为 62.5%(=10px),之后 1.6rem 就是 16px,心算友好。
步骤 4:百分比 %
相对父元素对应属性的值:
.parent { width: 400px; }
.child { width: 50%; } /* = 200px */
.child { font-size: 150%; } /* 相对父元素字号 */
坑:height: 50% 要父元素有明确高度才生效。
步骤 5:视口单位 vw / vh
1vw = 视口宽度的 1%,1vh = 视口高度的 1%:
.hero { height: 100vh; } /* 整屏 */
.headline { font-size: 5vw; } /* 字随屏变 */
.sidebar { width: 20vw; min-width: 200px; }
移动端 100vh 包含地址栏,要小心;现代方案用 100dvh(dynamic vh)。
步骤 6:函数 calc()、min()、max()、clamp()
/* calc:四则运算,混合单位 */
.sidebar { width: calc(100% - 200px); }
.card { padding: calc(1rem + 2vw); }
/* min/max:取小/取大 */
.box { width: min(500px, 90%); } /* 最多 500,至多 90% */
/* clamp:最小值, 偏好值, 最大值 */
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
/* 屏幕小给 1.5rem,屏幕大给 3rem,中间按 4vw 平滑过渡 */
clamp 是响应式排版的神器,一行实现流式字号。
步骤 7:var() 与 CSS 变量
:root {
--primary: #0366d6;
--gap: 16px;
}
.btn {
background: var(--primary);
padding: var(--gap);
color: var(--text-color, #fff); /* 第二个参数是兜底值 */
}
改一处变量,全站跟着变,是主题切换的基础。
讲清楚要点
- 默认字号:浏览器默认
16px,用户可在设置里改,所以用rem比px更友好(尊重用户偏好)。 - em 的相对对象会变:用在
font-size上相对父元素字号;用在padding等其他属性上相对当前元素自己的字号。 - 百分比相对谁?:宽度的 % 相对父元素宽度,高度的 % 相对父元素高度,
padding-top: 50%也是相对父元素宽度(不是高度!)。 - calc 注意空格:
calc(100% - 20px)减号两边必须空格,calc(100%-20px)是错的。 - vw/vh 含滚动条:
100vw包含纵向滚动条宽度,可能溢出。
你可能会懵的地方
-
em 和 rem 选哪个? 组件内部用 em(保持组件自包含),整体布局用 rem(保证全局一致)。
-
px 真的是绝对单位吗? 不完全是。在高 DPI 屏幕(Retina)上 1 CSS 像素可能等于 2 或 3 物理像素。
-
%在transform: translate(-50%, -50%)里相对谁? 相对元素自己的宽高。这是少数例外,常用于绝对居中。 -
vh 在手机上不准怎么办? 用
100dvh(dynamic viewport height)或100svh(small viewport height)。 -
calc 能算颜色吗? 不能,calc 只能算数值(长度、角度、时间、百分比)。颜色计算要用
color-mix()(新特性)。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
calc(100%-20px) | 减号两侧无空格 | calc(100% - 20px) |
嵌套 N 层 1.2em | 字号滚雪球失控 | 改用 rem |
height: 50% 父无高度 | 不生效 | 父元素加高度或用 vh |
width: 100vw 导致横向滚动 | 包含滚动条 | 用 width: 100% 或 100dvw |
移动端正文写 12px | 太小难读 | 用 rem 至少 14-16px |
var(--x) 拼错变量名 | 静默失效 | var(--x, fallback) 加兜底 |
卡点急救
- 字突然变很大或很小:F12 → Elements → Computed,看
font-size实际值,回溯是哪层 em/rem 计算错。 height: 100%不生效:父元素、爷爷元素都要height: 100%,一直链到html, body。- calc 报错:检查运算符两侧是否有空格,单位是否兼容(不能
10px - 5%……等等其实可以,calc 支持混合单位;但不能10px - red)。
面试常问
-
em 和 rem 的区别? em 相对当前元素或父元素字号(看用在哪个属性),rem 只相对根元素
<html>字号。rem 不会滚雪球,更适合做排版系统。 -
如何实现流式排版? 用
clamp(最小, 偏好, 最大),例如font-size: clamp(1rem, 0.5rem + 2vw, 2rem)。 -
vw/vh 在移动端有什么问题? 移动端地址栏会动态显隐,100vh 不准;用 dvh/svh/lvh 系列单位。
自测三问
font-size: 1.5em和padding: 1.5em相对谁计算?width: clamp(200px, 50%, 600px)在屏幕 800px 宽时实际值是多少?- 为什么
padding-top: 50%是相对宽度而不是高度?
小结一句话
单位选对了,布局就活了——精确用 px,全局比例用 rem,组件内部用 em,看屏用 vw/vh,流式用 clamp。
延伸
- MDN CSS 值与单位
- 下一课:颜色,学会用 hsl 控制明度饱和度。