
平时写页面接触最多的还是px、rem、%、vw/vh这几个老朋友。直到有一次做移动端 H5 适配被100vh在浏览器地址栏收起时“跳一下”的问题折腾到崩溃翻文档才发现 CSS 里已经悄悄多了几十个新单位svh、dvh、lvh、cqw、cqi、vi、vb、lh、rlh、ic、cap……第一反应是这些单位是认真的吗真的有人用吗这篇文章就从“筛选”的角度把这些新单位从名字到用法、从兼容性到实战场景过一遍分成“真正实用”“特定场景有用”“暂时用不上”三档。内容偏工程实践会有完整的代码示例和兼容性判断思路。新手可以当成 CSS 单位科普看前端老手可以当一份快速排查手册来用。1. 背景与核心概念1.1 CSS 单位不是新东西只是你太久没更新了CSS 单位并不是最近才有的概念。从 CSS1 开始就有px、pt、emCSS2 加入了exCSS3 引入了vw、vh、rem、ch再往后随着容器查询、逻辑属性、动态视口等规范落地又出现了大量新单位。可以按用途把 CSS 单位分成这几类分类典型单位特性绝对长度单位px、pt、cm、mm、in有物理含义但实际渲染受屏幕影响字体相对单位em、rem、ex、ch、ic、cap、lh、rlh以当前字体或根元素字体为基准视口相对单位vw、vh、vi、vb、vmin、vmax、svh、dvh、lvh以浏览器视口尺寸为基准容器相对单位cqw、cqh、cqi、cqb、cqmin、cqmax以最近的查询容器尺寸为基准弹性单位fr在 Grid / Flex 布局中按比例分配空间其他单位deg、s、dpi等角度、时间、分辨率等场景看到这里你应该能明白所谓“新单位”绝大多数不是凭空冒出来的而是 CSS 为了补齐视口适配、容器查询、逻辑属性、中文排版这些能力而新增的长度单位。1.2 新单位到底在解决什么问题新单位出现的核心驱动力有三个。第一个是移动端视口不稳定。手机浏览器地址栏隐藏和显示会导致视口高度实时变化旧的100vh在不同浏览器表现不一致于是出现了svh、lvh、dvh。第二个是组件化开发的响应式需求。媒体查询只能基于视口做响应没法让一个组件根据它自己父容器的宽度变化而自适应。容器查询和cqw、cqi等单位就是为了解决这个问题。第三个是书写模式和排版需求。随着国际化、多语言、中文排版越来越被重视CSS 提出了逻辑属性体系vi、vb这两个视口单位对应逻辑方向ic则是专门为 CJK中日韩文字设计的宽度单位。1.3 新单位 vs 旧单位是替换还是补充我的看法是新单位和旧单位不是简单的替换关系。vh、vw这种老单位在 desktop 端表现稳定仍然能继续用但在移动端全屏布局中dvh比vh更合适这里是一种“增强替换”。cqw和%看起来都能做百分比宽度但cqw的基准是“最近的查询容器”比百分比更可控这是一种“场景补充”。ic和ch都是字符宽度单位但一个对应中文一个对应英文数字是并列关系。所以新单位是 CSS 能力扩展的产物不是对旧体系的彻底推翻。实际开发中应该根据场景选择而不是盲目追求“用新单位显得高级”。2. 环境准备与兼容性说明2.1 浏览器支持情况概览CSS 新单位兼容性差距非常大。下面是我在实际开发中常见的新单位支持情况供参考单位Chrome / EdgeFirefoxSafari备注dvh/svh/lvh10810115.4移动端布局强推cqw/cqh/cqi/cqb10511016容器查询单位vi/vb10810115.4逻辑方向视口单位ic106不太稳定15中文排版实用lh/rlh支持有限有限适合渐进增强cap/rcap/ric等有限有限有限建议先查兼容性注意不同浏览器版本对这些单位的实现细节可能会有细微差别尤其是字体相关单位的计算方式。项目中要不要用、用到什么程度都应该以目标浏览器的实测结果为准。2.2 开发验证方式验证新单位最好的方式是本地起一个简单的 HTML 页面用浏览器 DevTools 的 Computed 面板查看最终计算出来的像素值。具体步骤如下编写一个最小 HTML 文件把要测试的 CSS 写进去。用浏览器打开右键检查目标元素。在 Computed 面板中查看width、height、font-size等属性的实际计算值。切换不同设备模拟模式观察单位值的变化。如果希望快速判断某个单位是否被当前浏览器支持也可以通过 JS 特性检测// 检测 dvh 是否支持 if (CSS.supports(height, 100dvh)) { console.log(100dvh 支持); } else { console.log(100dvh 不支持需要 fallback); }或者在 CSS 里用supportssupports (height: 100dvh) { .page { height: 100dvh; } }这个思路在后面做渐进增强时会反复用到。3. 容易被忽略的“老新单位”ch、ex、ic在聊最火的dvh和容器查询单位之前先看几个出现时间比较早但普及率不高的字体相对单位。它们不算“最新”但对很多开发者来说仍然是“以前没见过的新单位”。3.1 ch等宽字体排版的好帮手ch单位表示元素字体下数字0U0030的宽度。如果是等宽字体ch的宽度是固定的所以很适合做代码区块、字符统计类布局。先看一个最简单的例子.code-block { font-family: JetBrains Mono, Consolas, monospace; max-width: 80ch; margin: 0 auto; }这里的max-width: 80ch意思是“最多显示 80 个等宽字符”在代码展示场景中非常直观。即使是中英文混排只要确认字体是等宽字体ch能帮你省去手动计算宽度的麻烦。3.2 ex小写字母高度也能当尺子ex单位表示元素字体中小写字母x的高度。它通常用于对齐基线相关的场景。.icon { width: 1ex; height: 1ex; background: #333; border-radius: 50%; }如果你需要画一个和文字行内小写字母差不多大的圆点1ex会比1em更合适。不过ex的兼容性和计算稳定性不如em、rem实际项目中使用频率不高。3.3 ic中文字符的专属宽度单位ic单位表示元素字体下 CJK 表意字符的宽度。对中文网站来说ic比ch更符合实际排版需求。下面这段 CSS 可以实现中文段落首行缩进两个字符.article p { text-indent: 2ic; line-height: 1.8; }以后看到text-indent: 2em的写法大概率是旧项目如果面向中文场景2ic在语义上更准确也不会因为字体中英文混排而出现偏差。4. 最值得推荐的实用单位svh / dvh / lvh4.1 100vh 为什么会在手机上翻车很多前端都遇到过这个现象在移动端页面里给全屏容器设置height: 100vh顶部地址栏隐藏前后页面高度会突然变化底部按钮可能被遮挡或者出现一小截空白。原因在于移动端浏览器的视口高度会随地址栏显示状态变化。100vh指的是“当前视口高度”但浏览器在计算时往往取的是最大视口或者当前可见视口表现不一致于是产生了各种诡异布局。为了解决这个问题CSS 规范引入了小视口、大视口、动态视口三个概念。4.2 svh / lvh / dvh 的区别svh小视口高度。地址栏始终显示时视口的最小高度。lvh大视口高度。地址栏隐藏后视口的最大高度。dvh动态视口高度。会跟随地址栏显示状态实时变化。简单来说svh是最保守的值lvh是最大值dvh是浏览器当前实际视口高度。4.3 实际应用写法移动端全屏布局的推荐写法是.page { height: 100vh; /* 旧浏览器 fallback */ height: 100dvh; /* 支持丁 dvh 的浏览器使用动态视口 */ }dvh的好处是地址栏收起时页面自动跟着变高不会出现底部空白地址栏弹出时又自动收缩不会挡住底部操作栏。对话框、底部弹层这类“不能被遮挡”的容器则可以用svh作为约束.modal { max-height: 100svh; overflow-y: auto; }这样即使地址栏处于显示状态弹层主体也在可见区域内不会出现“被顶到屏幕外”的问题。5. 组件自适应的核心cqw / cqi / cqh5.1 容器查询和媒体查询有什么不一样媒体查询基于视口尺寸适合做“整个页面”的响应式布局。但业务开发中经常遇到一个组件在不同父容器里宽度不同却要呈现不同排版的情况。你总不能为每个组件都写一套媒体查询因为组件不知道自己所在的父容器有多宽。容器查询解决了这个问题它允许组件根据最近的查询容器的尺寸来调整样式。和容器查询一起出现的还有一组容器查询单位。5.2 容器查询单位详解单位含义cqw查询容器宽度的 1%cqh查询容器高度的 1%cqi查询容器内联方向尺寸的 1%cqb查询容器块方向尺寸的 1%cqmincqi和cqb中较小值的 1%cqmaxcqi和cqb中较大值的 1%在水平书写模式下cqi相当于cqwcqb相当于cqh。使用容器查询单位有一个前提元素的某个祖先必须设置container-type属性否则它无法获取容器尺寸。5.3 一个卡片组件自适应案例下面用一个卡片列表来演示容器查询单位和container的配合。HTML 结构div classcard-list div classcard h3 classcard__titleCSS 新单位卡片/h3 p classcard__desc这是一段用于演示容器查询单位的卡片描述。/p /div div classcard h3 classcard__title另一个卡片标题/h3 p classcard__desc不同容器宽度下卡片字号和布局会自动调整。/p /div /divCSS 代码.card-list { container-type: inline-size; container-name: card-list; } .card { padding: 16px; border-radius: 8px; background: #f5f6f8; } .card__title { font-size: 1.25rem; } .card__desc { font-size: 0.875rem; line-height: 1.6; } container card-list (min-width: 400px) { .card { display: flex; padding: 3cqw; } .card__title { font-size: 2.5cqw; } .card__desc { font-size: 1.4cqw; } }当.card-list宽度超过 400px 时卡片从垂直排列变成水平排列同时padding、font-size都会基于容器宽度计算。无论这个卡片列表是放在侧边栏、主内容区还是弹窗里它都能自动适配自己的宿主容器。5.4 容器查询单位的回退行为有一个容易踩的坑如果元素的祖先中不存在查询容器cqw这类单位会回退到视口单位。比如cqw会回退到svwcqi回退到svi。这个回退行为本意是保证页面不崩但容易导致“容器的容器没设置container-type结果字号跟着视口跳”的现象。使用容器查询单位时一定要确认最近的容器已经正确设置了container-type。6. 逻辑属性配套单位vi / vb6.1 什么是逻辑属性和逻辑方向传统 CSS 布局里的left、right、top、bottom是物理方向它们和页面的物理坐标绑定。但 CSS 发展到今天横向书写、竖排、RTL从右到左等场景越来越常见物理方向表达已经不够用了。于是 CSS 引入了逻辑属性体系inline内联方向和block块方向来替代物理方向。水平书写下inline方向就是水平方向block方向就是垂直方向竖排书写下两个方向会互换。常见的逻辑属性包括padding-inline、padding-blockmargin-inline、margin-blockborder-inline-start、border-block-endinset-inline、inset-block6.2 vi / vb 单位vi和vb是视口单位在逻辑方向上的变体vi视口内联方向尺寸的 1%。vb视口块方向尺寸的 1%。水平书写模式下vi等于vwvb等于vh竖排书写模式下vi等于vhvb等于vw。除此之外还有对应的动态/小/大视口变体svi、lvi、dvi、svb、lvb、dvb。6.3 实际使用示例.banner { padding-inline: 5vi; }这段代码会让.banner的左右内边距跟随视口内联方向尺寸变化。如果页面是水平书写模式效果和5vw一致。再看一个竖排场景.vertical-text { writing-mode: vertical-rl; padding-left: 5vi; }在vertical-rl竖排模式下内联方向变成了垂直方向5vi对应的是视口高度的 5%所以这个 padding 会用在垂直方向。如果你用vw它始终指向视口宽度在竖排布局中就会不符合预期。vi、vb的适用场景主要集中在需要适配多书写模式的项目。如果项目只需要水平书写的中文页面直接用vw、vh、dvh反而更直观。7. 排版相关的进阶单位lh / rlh / cap7.1 lh 和 rlh与行高对齐lh表示元素自身的行高rlh表示根元素通常是html的行高。它最大的价值在于某些时候需要让一个元素的高度和几行文字完全对齐。例如实现两行文字截断.card__desc { line-height: 1.6; max-height: 2lh; overflow: hidden; }这里max-height: 2lh的意思是“最多显示两行文字”比硬写max-height: 3.2em更直观而且和line-height的变化自动保持同步。rlh则适用于创建全局统一的垂直间距.section { margin-bottom: 2rlh; }这样页面里所有区块之间的间距都和根元素的行高比例保持一致视觉节奏更统一。不过要注意lh和rlh浏览器支持情况不如视口单位广泛。我的建议是主力浏览器已经支持但生产项目仍需谨慎。可以用supports做渐进增强不支持时回退到固定行高或em方案。7.2 cap大写字母高度cap表示字体中大写字母的高度。它适合用于需要和大写字母对齐的 UI 元素比如按钮图标、标签等。.tag { height: 2cap; }但因为浏览器支持有限实际应用价值不算高。对大写场景不多的中文项目来说可以暂时不用关注。7.3 r 系列根字体单位CSS 还定义了rcap、rch、ric、rex、rlh这些以根元素字体为基准的相对单位。它们的作用和cap、ch、ic、ex、lh类似只是基准从“当前元素字体”换成了“根元素字体”。从规范角度来说这些单位完善了字体相对单位体系但实际项目里用到它们的地方很少。一方面是因为场景太细另一方面是兼容性参差不齐。我的建议是先了解概念生产环境别急着用等目标浏览器支持了再考虑。8. 完整实战移动端 H5 阅读页 自适应卡片下面用一个移动端 H5 阅读页把前面提到的主要新单位串起来。页面包含页面整体占满动态视口。顶部标题栏固定。中间内容区可滚动中文段落首行缩进两字符。底部操作栏跟随安全区。卡片列表根据容器宽度自适应字号和间距。8.1 HTML 结构!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleCSS 新单位实战示例/title link relstylesheet hrefstyle.css /head body div classapp header classapp__header h1CSS 新单位实战阅读页/h1 /header main classapp__main article classarticle p这段文字用来演示中文首行缩进效果。移动端视口高度不断变化动态视口单位可以让页面整体不错位。/p h2推荐卡片/h2 div classcard-list div classcard h3 classcard__title卡片标题 A/h3 p classcard__desc这是一段卡片描述根据卡片列表容器宽度自适应字号。/p /div div classcard h3 classcard__title卡片标题 B/h3 p classcard__desc另一段卡片描述容器变宽时布局会自动调整。/p /div /div /article /main footer classapp__footer button classbtn确认阅读/button /footer /div /body /html8.2 CSS 核心代码/* 基础重置 */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: PingFang SC, Microsoft YaHei, sans-serif; color: #222; } /* 应用容器使用动态视口单位 */ .app { display: flex; flex-direction: column; height: 100vh; height: 100dvh; /* 动态视口移动端地址栏收起时跟随变化 */ } /* 顶部标题栏 */ .app__header { flex: 0 0 56px; display: flex; align-items: center; padding: 0 16px; border-bottom: 1px solid #eee; background: #fff; } .app__header h1 { font-size: 18px; } /* 主内容区 */ .app__main { flex: 1; overflow-y: auto; padding: 16px; } /* 中文段落首行缩进两字符 */ .article p { text-indent: 2ic; line-height: 1.8; margin-bottom: 16px; } .article h2 { font-size: 20px; margin-bottom: 12px; } /* 卡片列表容器开启容器查询 */ .card-list { container-type: inline-size; container-name: card-list; } /* 卡片基础样式 */ .card { padding: 16px; margin-bottom: 12px; border-radius: 10px; background: #f5f6f8; } .card__title { font-size: 16px; margin-bottom: 6px; } .card__desc { font-size: 14px; line-height: 1.6; color: #555; } /* 容器宽度超过 400px 时使用容器查询单位 */ container card-list (min-width: 400px) { .card { display: flex; align-items: center; justify-content: space-between; padding: 2cqw; } .card__title { font-size: 2.4cqw; } .card__desc { font-size: 1.4cqw; } } /* 底部操作栏 */ .app__footer { flex: 0 0 auto; padding: 12px 16px; padding-bottom: calc(12px env(safe-area-inset-bottom)); background: #fff; border-top: 1px solid #eee; } .btn { width: 100%; height: 44px; border: none; border-radius: 8px; background: #1677ff; color: #fff; font-size: 16px; cursor: pointer; }8.3 运行与验证在浏览器中打开这个页面然后切换设备模拟模式模拟 iPhone 或 Android 手机。滚动页面观察底部操作栏是否始终贴底。打开 DevTools把.app的高度计算值从100vh改为100dvh前后对比确认移动端地址栏隐藏时高度变化。把页面宽度拉宽观察卡片列表在容器宽度超过 400px 后卡片内边距和字号是否平滑变化。这个例子把dvh、ic、cqw、container都串起来了。你可以在此基础上继续扩展其他新单位。9. 常见问题与排查思路问题现象常见原因解决思路100dvh在旧手机上无效浏览器版本不支持先写100vh再写100dvh兜底cqw字号没有随容器变化父级未设置container-type给容器添加container-type: inline-sizelh在 Safari 上不生效浏览器对lh支持有限用固定行高 overflow或supports降级vi/vb在竖排文本中表现不符合预期对逻辑方向理解偏差先确认writing-mode和direction中文字体下ch单位不准ch是基于数字0的宽度并非中文宽度中文场景改用ic或em浏览器不能识别某个单位样式直接失效未使用supports或 fallback先写旧单位再用新单位覆盖如果遇到新单位相关报错可以按下面顺序排查打开浏览器控制台确认是不是编译或解析错误。在 DevTools 的 Elements 面板中检查目标元素看样式是否被浏览器解析。看 Computed 面板中目标属性最终算出的像素值判断单位是否生效。用CSS.supports()或supports做特性检测确认浏览器是否支持。查 caniuse 或 MDN确认当前目标浏览器的支持情况。如果是生产环境优先加 fallback而不是临时删掉新单位。10. 最佳实践与工程建议10.1 新单位选型策略不同场景对应不同的新单位做一个简单总结场景推荐单位理由移动端全屏容器dvhvhfallback随地址栏状态动态变化弹层、底部浮层svh避免被地址栏遮挡中文段落缩进ic语义准确排版更自然组件内部自适应cqw/cqi跟随最近容器不用写媒体查询多语言/竖排布局vi/vb逻辑方向更可靠固定行数截断lh和行高自动同步全局垂直间距rlh和根元素行高保持一致10.2 渐进增强与降级新单位兼容性参差不齐工程上建议采用“渐进增强 降级”的思路。最基础的做法是旧单位写在前面、新单位写在后面.hero { height: 100vh; height: 100dvh; }浏览器会优先采用它能识别的最后一个声明。不支持的浏览器直接跳过100dvh使用100vh语义上也不会太差。对于影响布局比较大的属性使用supports包一层.page { height: 100vh; } supports (height: 100dvh) { .page { height: 100dvh; } }这种方式能保证即使浏览器不支持新单位旧样式依然生效。使用cqw等容器查询单位时务必为祖先容器设置container-type避免单位回退到视口单位导致样式“看起来没反应”。10.3 团队协作与测试建议新单位不是用上就完事它会影响整个团队的样式维护。项目里引入前建议做三件事第一在项目的样式规范文档里记录浏览器支持基线并注明哪些单位允许直接用、哪些单位必须加 fallback。第二新单位引入前先在一台目标测试机上实测尤其是lh、rlh、cap这类支持较差的字体相对单位。不要只看 caniuse 的数据因为字体不同实际渲染值可能不一样。第三可以用supports做特性检测或者写一组简单的单元测试页面把新单位的计算结果跑一遍避免浏览器升级后行为变化影响线上页面。10.4 什么时候真的不需要新单位新单位虽好但也不是所有项目都要用。如果项目只是做简单后台管理系统视口稳定、设备形式单一继续用px、rem、flex布局完全没问题。如果项目是内容型 H5、跨端组件库、复杂业务页面才需要考虑引入dvh、容器查询单位这些新特性。核心原则是先看需求再选单位。不要为了“炫技”把本来稳定的项目搞乱。写在最后CSS 单位越来越多不是 CSS 在变臃肿而是浏览器、设备、排版需求越来越复杂。svh、dvh、容器查询单位、ic这些真正解决日常痛点的单位值得在项目中逐步引入那些支持差、场景窄的单位知道有这回事就行不用硬上。下次写移动端页面再遇到100vh的坑可以试着把height改成100dvh写中文段落时text-indent换成2ic。这些小改动不会引人注意但会让页面更稳、更符合设计预期。如果你觉得这篇文章对你有帮助可以收藏备用。真正动手写项目时再对照这份单位清单慢慢选。