CSS 单位全面解析
在 CSS 中,几乎所有涉及"大小"的属性——宽度、高度、字体大小、间距、边框……都需要一个数值 + 单位来表达。选择正确的单位,直接影响页面的响应式表现和可维护性。本文将系统梳理 CSS 中所有常用单位,帮助你在不同场景下做出最佳选择。
一、绝对单位
绝对单位的大小是固定不变的,不会随父元素、视口大小或用户设置而变化。你可以把它们理解为"标尺上的刻度"——1px 永远是 1px(在相同设备像素比下)。
1.1 px(像素)
px 是 CSS 中最常用的绝对单位,也是最基础的尺寸单位。
.box {
width: 200px;
height: 100px;
font-size: 16px;
border: 1px solid #333;
}
CSS 中的 px 是逻辑像素(也叫 CSS 像素),不等于屏幕上的物理像素。在高清屏(Retina 屏幕)上,1 个 CSS 像素通常对应 2×2 个甚至 3×3 个物理像素。这个比例叫做设备像素比(DPR,Device Pixel Ratio)。
CSS 像素 × DPR = 物理像素
16px × 2 = 32 物理像素(在 2x Retina 屏上)
px 的适用场景:
| 场景 | 说明 |
|---|---|
| 边框宽度 | border: 1px solid #ddd; — 需要精确的细线 |
| 阴影偏移 | box-shadow: 2px 2px 4px rgba(0,0,0,.2); |
| 固定尺寸图标 | 如 width: 24px; height: 24px; |
| 细微间距 | 像素级的精确微调 |
1.2 其他绝对单位
除了 px,CSS 还支持以下绝对单位,它们之间有固定的换算关系:
| 单位 | 名称 | 与 px 的关系 | 主要用途 |
|---|---|---|---|
pt | 点(Point) | 1pt = 1.333px(96/72) | 打印样式 |
pc | 派卡(Pica) | 1pc = 16px | 打印排版 |
cm | 厘米 | 1cm ≈ 37.8px | 打印样式 |
mm | 毫米 | 1mm ≈ 3.78px | 打印样式 |
in | 英寸(Inch) | 1in = 96px | 打印样式 |
/* 打印样式中使用物理单位 */
@media print {
body {
font-size: 12pt; /* 打印常用字号 */
margin: 2cm; /* 打印页边距 */
}
}
cm、mm、in 等物理单位在屏幕上的实际显示大小取决于设备的 DPI 设置,并不能保证与真实物理尺寸一致。它们主要用于打印样式表(@media print),在屏幕布局中应优先使用 px 或相对单位。
二、相对单位 —— 字体相关
相对单位的值不是固定的,而是相对于某个参照物计算出来的。字体相关的相对单位以文字大小为参照,是构建弹性布局和可访问性友好页面的核心工具。
2.1 em
em 是相对于当前元素的 font-size 计算的单位。如果用在 font-size 属性本身上,则相对于父元素的 font-size。
.parent {
font-size: 16px;
}
.child {
font-size: 1.5em; /* 16px × 1.5 = 24px */
padding: 1em; /* 相对于自身 font-size:24px × 1 = 24px */
margin-bottom: 0.5em; /* 24px × 0.5 = 12px */
}
em 的核心特点:参照物会变
em 最大的特点——也是最容易踩坑的地方——是它的参照物取决于上下文。当 em 嵌套使用时,会产生复利效应:
.level-1 { font-size: 1.2em; } /* 假设根元素 16px → 19.2px */
.level-2 { font-size: 1.2em; } /* 19.2px × 1.2 = 23.04px */
.level-3 { font-size: 1.2em; } /* 23.04px × 1.2 = 27.65px */
<div class="level-1">
第一层:19.2px
<div class="level-2">
第二层:23.04px(越来越大!)
<div class="level-3">
第三层:27.65px(继续放大!)
</div>
</div>
</div>
由于 em 在 font-size 中相对于父元素计算,多层嵌套会导致字体大小逐级放大或缩小,难以预测最终结果。这就是 rem 被发明出来的原因。
em 的适用场景:
- 组件内部间距:
padding、margin用em可以让间距随字体大小自动缩放 - 按钮、标签等内联组件:让内边距与文字大小保持比例协调
/* 不同尺寸的按钮,间距自动跟随字体缩放 */
.btn {
padding: 0.5em 1em;
border-radius: 0.25em;
}
.btn-sm { font-size: 12px; } /* padding: 6px 12px */
.btn-md { font-size: 16px; } /* padding: 8px 16px */
.btn-lg { font-size: 20px; } /* padding: 10px 20px */
2.2 rem(Root em)
rem 是相对于根元素 <html> 的 font-size 计算的单位。无论元素嵌套多深,1rem 的大小始终相同——这就是它名字中 "Root" 的含义。
html {
font-size: 16px; /* 浏览器默认值 */
}
h1 {
font-size: 2rem; /* 16px × 2 = 32px */
margin-bottom: 1rem; /* 16px × 1 = 16px */
}
.card {
padding: 1.5rem; /* 16px × 1.5 = 24px */
font-size: 1rem; /* 16px × 1 = 16px */
}
/* 无论嵌套多深,rem 的参照物始终是 html 的 font-size */
.level-1 .level-2 .level-3 {
font-size: 1.2rem; /* 始终是 16px × 1.2 = 19.2px */
}
rem vs em 对比:
| 特性 | em | rem |
|---|---|---|
| 参照物 | 当前元素(或父元素)的 font-size | 根元素 <html> 的 font-size |
| 嵌套行为 | 逐级累积,产生复利效应 | 始终一致,不受嵌套影响 |
| 可预测性 | 低(需要追踪上下文) | 高(只看根元素) |
| 适用场景 | 组件内部间距、需随字体缩放的尺寸 | 全局排版、布局间距、字体大小 |
- 字体大小用
rem:全局统一、可预测 - 组件内间距用
em:间距随字体自动缩放 - 布局间距用
rem:不受组件字体大小影响
2.3 62.5% 技巧
在实际开发中,16px 作为基准值计算不太方便(1.5rem = 24px、0.875rem = 14px……很难心算)。一个常用的技巧是将根元素字体设为 62.5%:
html {
font-size: 62.5%; /* 16px × 62.5% = 10px */
}
body {
font-size: 1.6rem; /* 恢复为 16px,正文保持正常 */
}
/* 现在 rem 的换算变得非常直观 */
h1 { font-size: 3.2rem; } /* 32px */
h2 { font-size: 2.4rem; } /* 24px */
p { font-size: 1.6rem; } /* 16px */
.small { font-size: 1.2rem; } /* 12px */
这个技巧虽然方便计算,但也有缺点:
- 需要在
body上手动恢复字体大小 - 第三方库如果使用
rem,其字体大小会变小(因为根字号变成了 10px) - 部分团队规范不允许修改根字号
现代开发中,借助 CSS 变量和编辑器插件(如 px-to-rem),即使不用这个技巧也能高效开发。
2.4 ch 和 ex
这两个单位不太常用,但在特定场景下很有用:
| 单位 | 含义 | 典型值(16px 字体) |
|---|---|---|
ch | 字符 "0" 的宽度 | ≈ 8px(等宽字体中精确对应) |
ex | 小写字母 "x" 的高度 | ≈ 8px(约为 font-size 的一半) |
/* ch 的经典用途:限制每行字符数,提升阅读体验 */
.article {
max-width: 70ch; /* 大约 70 个字符宽度,适合阅读 */
}
/* 等宽字体的输入框宽度 */
input.code {
font-family: monospace;
width: 20ch; /* 精确放下 20 个字符 */
}
2.5 lh 和 rlh
CSS 新增的行高相关单位:
| 单位 | 含义 |
|---|---|
lh | 当前元素的 line-height 计算值 |
rlh | 根元素的 line-height 计算值 |
html {
font-size: 16px;
line-height: 1.5; /* 16px × 1.5 = 24px */
}
.spacer {
height: 2rlh; /* 24px × 2 = 48px,刚好两行高 */
}
三、相对单位 —— 视口相关
视口(Viewport)指的是浏览器窗口中用于显示网页的区域。视口单位相对于视口大小进行计算,是实现全屏布局和响应式设计的利器。
3.1 基础视口单位
| 单位 | 含义 | 计算方式 |
|---|---|---|
vw | 视口宽度的 1% | 100vw = 视口全宽 |
vh | 视口高度的 1% | 100vh = 视口全高 |
vmin | vw 和 vh 中较小的那个 | 取小值 |
vmax | vw 和 vh 中较大的那个 | 取大值 |
/* 全屏 Hero 区域 */
.hero {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
/* 响应式字体:随视口宽度缩放 */
.title {
font-size: 5vw; /* 视口宽 1200px 时字号为 60px */
}
/* vmin 保证在横屏和竖屏下都不会太大 */
.logo {
width: 20vmin;
height: 20vmin;
}
vmin 和 vmax 的妙用:
/* 无论设备横屏还是竖屏,元素都保持可见比例 */
.responsive-box {
width: 50vmin; /* 始终占较短边的 50% */
height: 50vmin;
}
/* vmax 制作自适应大标题 */
.headline {
font-size: 8vmax; /* 始终以较长边为参照,确保足够大 */
}
3.2 移动端 100vh 的坑
在移动端浏览器中,100vh 的表现往往不如预期。这是因为移动浏览器的地址栏会收缩和展开,导致实际可见区域的高度在变化,但 100vh 的值却不随之改变:
这意味着当地址栏展开时,设置 height: 100vh 的元素会有一部分被地址栏遮挡,用户需要滚动才能看到底部内容。
3.3 新视口单位(解决移动端问题)
为了解决上述问题,CSS 引入了三组新的视口单位:
| 类型 | 宽度 | 高度 | 含义 |
|---|---|---|---|
| Small Viewport | svw | svh | 视口最小状态(地址栏展开时) |
| Large Viewport | lvw | lvh | 视口最大状态(地址栏收缩时) |
| Dynamic Viewport | dvw | dvh | 视口当前实际状态(动态变化) |
/* ✅ 推荐:移动端全屏布局 */
.hero {
height: 100dvh; /* 动态视口高度,始终填满可见区域 */
}
/* 安全方案:确保内容不被遮挡 */
.container {
min-height: 100svh; /* 使用最小视口,最保守 */
}
/* 需要填满最大空间时 */
.fullscreen {
height: 100lvh; /* 使用最大视口高度 */
}
dvh动态视口:适合大多数场景(全屏 Hero、弹窗等),实时跟随视口变化svh小视口:适合需要确保内容始终完全可见的场景,最安全lvh大视口:适合需要铺满整个屏幕的背景图或视频
同样地,vmin 和 vmax 也有对应的新版本:svmin、svmax、lvmin、lvmax、dvmin、dvmax。
3.4 容器查询单位(cqw / cqh)
容器查询单位是 CSS 最新引入的相对单位,它们相对于最近的容器查询祖先的尺寸来计算:
| 单位 | 含义 |
|---|---|
cqw | 容器宽度的 1% |
cqh | 容器高度的 1% |
cqi | 容器内联尺寸的 1% |
cqb | 容器块尺寸的 1% |
cqmin | cqi 和 cqb 中较小的那个 |
cqmax | cqi 和 cqb 中较大的那个 |
/* 定义一个查询容器 */
.card-container {
container-type: inline-size;
container-name: card;
}
/* 子元素使用容器查询单位 */
.card-container .title {
font-size: 5cqw; /* 字号为容器宽度的 5% */
}
/* 配合容器查询使用 */
@container card (min-width: 400px) {
.card-container .title {
font-size: 3cqw; /* 容器较宽时,比例适当降低 */
}
}
传统的视口单位(vw、vh)相对于整个浏览器窗口,而容器查询单位相对于组件所在的容器。这意味着同一个组件在不同宽度的容器中可以自动调整自身尺寸,真正实现了组件级别的响应式设计。
四、百分比(%)
百分比也是一种相对单位,但它的参照物比较复杂——不同属性的百分比参照不同的东西。
4.1 常见属性的百分比参照
| 属性 | 参照物 | 说明 |
|---|---|---|
width | 父元素的 width | 最常见、最直觉的用法 |
height | 父元素的 height | 父元素必须有明确的高度值才生效 |
padding | 父元素的 width | 注意:即使是 padding-top/bottom,参照的也是宽度! |
margin | 父元素的 width | 同上,margin-top/bottom 也参照宽度 |
font-size | 父元素的 font-size | 类似 em 的效果 |
line-height | 元素自身的 font-size | line-height: 150% 等同于 1.5em |
top / bottom | 定位参照元素的 height | 需要 position 非 static |
left / right | 定位参照元素的 width | 需要 position 非 static |
transform: translate() | 元素自身的宽高 | 这是唯一参照自身尺寸的情况 |
background-size | 元素自身的宽高 | background-size: 50% = 背景图占元素宽度的一半 |
4.2 padding 百分比的妙用:固定宽高比
padding 百分比始终参照父元素的宽度这个特性,催生了一个经典的"宽高比盒子"技巧:
/* 16:9 宽高比容器(传统技巧) */
.aspect-ratio-box {
width: 100%;
padding-top: 56.25%; /* 9/16 × 100% = 56.25% */
position: relative;
}
.aspect-ratio-box > .content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
CSS 现在有了原生的 aspect-ratio 属性,可以直接替代 padding hack:
/* 现代写法,简洁直观 */
.video-wrapper {
width: 100%;
aspect-ratio: 16 / 9;
}
4.3 height 百分比的"失效"问题
height: 100% 是新手最常遇到的困惑之一——为什么设置了 height: 100% 却没有效果?
/* ❌ 这样写 .child 的高度不会生效 */
.parent {
/* 没有设置明确的 height */
}
.child {
height: 100%; /* 100% 的什么?父元素没有高度参照! */
}
/* ✅ 解决方案 1:给父元素设定明确高度 */
.parent {
height: 500px;
}
.child {
height: 100%; /* 500px × 100% = 500px */
}
/* ✅ 解决方案 2:使用 vh 替代 */
.child {
height: 100vh; /* 直接参照视口高度,不依赖父元素 */
}
/* ✅ 解决方案 3:使用 Flexbox 或 Grid */
.parent {
display: flex;
flex-direction: column;
}
.child {
flex: 1; /* 自动填充剩余空间 */
}
五、无单位值
有些 CSS 属性接受无单位的纯数字,它们在特定场景下比带单位的值更优。
5.1 line-height 的无单位写法
line-height 是无单位值最重要的应用场景:
/* ❌ 带单位的 line-height:子元素继承的是计算后的固定值 */
.parent {
font-size: 16px;
line-height: 24px; /* 或 1.5em / 150% */
}
.child {
font-size: 32px;
/* 继承到的 line-height 仍然是 24px,文字重叠! */
}
/* ✅ 无单位的 line-height:子元素继承的是比例因子 */
.parent {
font-size: 16px;
line-height: 1.5; /* 无单位 */
}
.child {
font-size: 32px;
/* line-height = 32px × 1.5 = 48px,比例保持一致 */
}
line-height: 1.5em/line-height: 150%:继承的是计算后的值(如 24px)line-height: 1.5(无单位):继承的是比例因子(1.5),子元素会用自己的font-size重新计算
推荐始终使用无单位的 line-height。
5.2 其他接受无单位值的属性
| 属性 | 说明 | 示例 |
|---|---|---|
line-height | 行高比例因子 | line-height: 1.5 |
flex-grow / flex-shrink | Flex 伸缩比例 | flex-grow: 2 |
order | Flex/Grid 排列顺序 | order: -1 |
z-index | 层叠顺序 | z-index: 100 |
opacity | 透明度(0~1) | opacity: 0.8 |
scale | 缩放倍数 | scale: 1.5 |
font-weight | 字重 | font-weight: 700 |
animation-iteration-count | 动画重复次数 | animation-iteration-count: 3 |
六、单位选择指南
6.1 不同场景的推荐单位
6.2 完整推荐表
| 使用场景 | 推荐单位 | 原因 |
|---|---|---|
font-size | rem | 全局一致,方便统一缩放 |
line-height | 无单位 | 子元素可正确重新计算 |
width(弹性布局) | % / fr | 相对父容器自适应 |
max-width(阅读宽度) | ch | 基于字符数,提升可读性 |
height(全屏) | dvh / svh | 移动端兼容 |
padding / margin | rem 或 em | rem 用于布局间距,em 用于组件内间距 |
border-width | px | 需要精确像素控制 |
border-radius | px 或 % | px 固定圆角,% 做椭圆/圆形 |
box-shadow | px | 阴影偏移和模糊需要精确值 |
media query 断点 | em | 不受用户根字号设置影响 |
| 打印样式 | pt / cm | 对应物理世界的度量 |
6.3 响应式字体的 clamp() 技巧
clamp() 函数可以同时设置最小值、理想值、最大值,配合视口单位实现流畅的响应式字体:
/* clamp(最小值, 理想值, 最大值) */
h1 {
/* 最小 24px,理想为视口宽度的 5%,最大 60px */
font-size: clamp(1.5rem, 5vw, 3.75rem);
}
p {
/* 最小 16px,理想为 1rem + 视口的 0.5%,最大 20px */
font-size: clamp(1rem, 1rem + 0.5vw, 1.25rem);
}
这比纯 vw 更好,因为它设置了上下限,避免在超大或超小屏幕上字体太离谱。
/* 完整的响应式排版系统 */
:root {
--fs-sm: clamp(0.875rem, 0.8rem + 0.25vw, 1rem);
--fs-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--fs-lg: clamp(1.25rem, 1rem + 1vw, 1.75rem);
--fs-xl: clamp(1.5rem, 1rem + 2vw, 2.5rem);
--fs-2xl: clamp(2rem, 1.2rem + 3vw, 3.5rem);
}
body { font-size: var(--fs-base); }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
small { font-size: var(--fs-sm); }
七、单位换算与计算
7.1 常用换算公式
/* px 与 rem 互转(假设根字号 16px) */
rem = px / 16
px = rem × 16
/* px 与 em 互转(需知道当前元素的 font-size) */
em = px / 当前元素的 font-size
px = em × 当前元素的 font-size
/* px 与 vw 互转(需知道视口宽度) */
vw = px / 视口宽度 × 100
px = vw × 视口宽度 / 100
/* 百分比与 px 互转(需知道参照值) */
% = px / 参照值 × 100
px = % × 参照值 / 100
7.2 常见 px → rem 速查表(根字号 16px)
| px | rem | px | rem |
|---|---|---|---|
| 10px | 0.625rem | 28px | 1.75rem |
| 12px | 0.75rem | 32px | 2rem |
| 14px | 0.875rem | 36px | 2.25rem |
| 16px | 1rem | 40px | 2.5rem |
| 18px | 1.125rem | 48px | 3rem |
| 20px | 1.25rem | 56px | 3.5rem |
| 24px | 1.5rem | 64px | 4rem |
7.3 calc() 混合运算
calc() 函数允许不同单位混合计算,浏览器会在渲染时自动转换:
.sidebar {
/* 固定宽度 + 相对间距 */
width: calc(100% - 250px);
}
.hero {
/* 全屏高度减去导航栏 */
height: calc(100dvh - 64px);
}
.card {
/* rem 和 px 混合 */
padding: calc(1rem + 4px);
}
/* 高级用法:CSS 变量 + calc */
:root {
--sidebar-width: 250px;
--nav-height: 64px;
}
.main {
width: calc(100% - var(--sidebar-width));
min-height: calc(100dvh - var(--nav-height));
}
- 运算符(
+、-)两边必须有空格:calc(100% - 20px)✅ /calc(100%-20px)❌ - 乘法和除法的一端必须是无单位数字:
calc(2rem * 3)✅ /calc(2rem * 3px)❌ calc()可以嵌套使用:calc(calc(100% - 20px) / 2)— 但通常直接写calc((100% - 20px) / 2)更清晰
八、浏览器兼容性
8.1 各单位浏览器支持情况
| 单位 | Chrome | Firefox | Safari | Edge | 状态 |
|---|---|---|---|---|---|
px, em, % | 全版本 | 全版本 | 全版本 | 全版本 | 基础支持 |
rem | 4+ | 3.6+ | 5+ | 12+ | 广泛支持 |
vw, vh | 26+ | 19+ | 7+ | 12+ | 广泛支持 |
vmin, vmax | 26+ | 19+ | 7+ | 12+ | 广泛支持 |
ch | 27+ | 1+ | 7+ | 12+ | 广泛支持 |
dvh, svh, lvh | 108+ | 101+ | 15.4+ | 108+ | 现代浏览器支持 |
cqw, cqh | 105+ | 110+ | 16+ | 105+ | 现代浏览器支持 |
lh, rlh | 132+ | 132+ | 16.4+ | 132+ | 较新支持 |
8.2 渐进增强策略
对于较新的单位,推荐使用渐进增强的写法——先写兼容的旧单位作为回退,再写新单位:
.hero {
/* 回退方案 */
height: 100vh;
/* 支持新单位的浏览器会使用这个 */
height: 100dvh;
}
.card-title {
/* 回退方案 */
font-size: 1.5rem;
/* 支持容器查询单位的浏览器会使用这个 */
font-size: clamp(1rem, 5cqw, 2rem);
}
也可以使用 @supports 进行特性检测:
.hero {
height: 100vh;
}
@supports (height: 100dvh) {
.hero {
height: 100dvh;
}
}
九、综合实战
9.1 构建一个响应式卡片组件
综合运用不同 CSS 单位:
:root {
font-size: 16px;
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
}
.card {
/* 布局尺寸用百分比 */
width: 100%;
max-width: 400px;
/* 间距用 rem,全局一致 */
padding: var(--spacing-lg);
margin-bottom: var(--spacing-md);
/* 边框用 px,精确控制 */
border: 1px solid #e0e0e0;
border-radius: 8px;
/* 阴影用 px */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card__title {
/* 字体用 rem */
font-size: 1.5rem;
line-height: 1.3; /* 无单位 */
margin-bottom: 0.5em; /* em:随标题字号缩放 */
}
.card__body {
font-size: 1rem;
line-height: 1.6; /* 无单位 */
/* 限制行宽提升阅读体验 */
max-width: 65ch;
}
.card__image {
width: 100%;
/* 现代宽高比写法 */
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 4px;
}
9.2 全屏 Hero + 响应式排版
.hero {
/* 视口单位:全屏布局 */
width: 100vw;
min-height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* rem 间距 */
padding: 2rem;
}
.hero__title {
/* clamp 响应式字体 */
font-size: clamp(2rem, 1rem + 4vw, 4.5rem);
line-height: 1.1;
text-align: center;
}
.hero__subtitle {
font-size: clamp(1rem, 0.8rem + 1vw, 1.5rem);
line-height: 1.5;
max-width: 60ch; /* 限制阅读宽度 */
text-align: center;
margin-top: 1em; /* em:随字体大小缩放 */
}
十、面试高频问答
Q1:px、em、rem 的区别是什么?
答:px 是绝对单位,大小固定不变;em 是相对单位,相对于当前元素(或父元素)的 font-size;rem 也是相对单位,但始终相对于根元素 <html> 的 font-size。rem 解决了 em 在嵌套场景下会逐级累积的问题,在实际开发中 rem 用于全局字体和布局间距,em 用于组件内需要随字体缩放的间距。
Q2:vw、vh 和百分比有什么区别?
答:vw / vh 相对于浏览器视口的宽度和高度,而百分比 % 相对于父元素的对应属性(通常是父元素的宽度或高度)。例如 width: 50% 是父元素宽度的一半,而 width: 50vw 是浏览器窗口宽度的一半。在嵌套结构中,百分比受父元素影响,而视口单位不受嵌套影响,始终参照视口大小。
Q3:为什么移动端 100vh 会有问题?怎么解决?
答:移动端浏览器有可收缩的地址栏,100vh 取的是地址栏收缩后的最大视口高度。当地址栏展开时,实际可见区域小于 100vh,导致底部内容被遮挡。解决方案:
- 使用
100dvh(动态视口高度),它会随地址栏状态实时变化 - 使用
100svh(小视口高度),取最小可见区域,最保守 - 使用 JavaScript 动态计算:
window.innerHeight - 使用 CSS 变量配合 JS:
document.documentElement.style.setProperty('--vh', window.innerHeight * 0.01 + 'px')
Q4:line-height: 1.5 和 line-height: 1.5em 有什么区别?
答:虽然在当前元素上计算结果相同,但继承行为完全不同。line-height: 1.5(无单位)继承的是比例因子 1.5,子元素会用自己的 font-size 重新计算;line-height: 1.5em 继承的是计算后的固定值(如父元素字号 16px 时为 24px),子元素即使字号更大也只有 24px 的行高,导致文字重叠。因此推荐始终使用无单位的 line-height。
Q5:padding 的百分比为什么参照的是父元素的宽度而不是高度?
答:CSS 规范规定 padding 和 margin 的百分比值统一参照包含块的宽度(inline size),这是为了保证垂直和水平方向的百分比值有相同的参照基准。如果 padding-top 参照高度、padding-left 参照宽度,那么 padding: 10% 在四个方向上的值就不一致。统一参照宽度可以避免这种不一致,也使得用 padding-top 百分比来实现宽高比盒子成为可能。
Q6:什么是 CSS 像素?它和物理像素的关系是什么?
答:CSS 像素(也叫逻辑像素)是 CSS 中使用的抽象单位,物理像素是屏幕上实际的发光点。它们之间的关系由**设备像素比(DPR)**决定:物理像素 = CSS 像素 × DPR。在普通屏幕上 DPR 为 1(1 CSS 像素 = 1 物理像素),在 Retina 屏幕上 DPR 为 2 或 3(1 CSS 像素对应 4 或 9 个物理像素),所以同样 font-size: 16px 在 Retina 屏上看起来更精细但物理尺寸相同。
Q7:如何实现响应式字体大小?
答:推荐使用 clamp() 函数:font-size: clamp(最小值, 理想值, 最大值)。例如 font-size: clamp(1rem, 1rem + 2vw, 3rem) 可以让字体在 16px~48px 之间随视口宽度平滑变化。相比纯 vw 单位,clamp() 设置了上下限,避免在极端尺寸下字体过大或过小。这种方案无需媒体查询断点,实现了真正流畅的响应式排版。
Q8:calc() 的使用规则有哪些?
答:
+和-运算符两边必须有空格,否则会解析错误*和/的一端必须是无单位数字,不能两端都带单位- 可以混合不同单位运算,如
calc(100% - 2rem) - 可以嵌套使用,但推荐用括号代替嵌套以提高可读性
- 除数不能为 0
- 可以和 CSS 变量配合使用:
calc(var(--width) * 2)