根本原因是vw()函数隐含三个未经校验的假设:设计稿宽度固定为375px、所有设备支持vw、所有CSS属性都适合转vw;实际需校验单位、限定适用属性、用dvh替代vh并提供fallback。

为什么直接写 vw() 函数会在线上出问题
编译不报错,但字体发虚、按钮错位、小屏元素溢出——根本原因不是语法错,而是函数隐含了三个未经校验的假设:设计稿宽度固定为 375px、所有设备支持 vw、所有 CSS 属性都适合转 vw。实际项目里,设计稿可能是 750px;IE11、旧版安卓 WebView 不支持 vw;border 或 box-shadow 用 vw 后在 iPhone SE 上渲染成 0.5px,模糊失真。
vw() 函数必须带单位检查和基准变量
SCSS 编译期不校验单位类型,传入 16em 或 20% 会导致静默错误或中断编译。函数必须主动拦截非 px 值,并把基准宽度抽成变量而非硬编码。
- 用
@if unit($px) != 'px'检查输入单位,否则抛错:@error 'vw() expects a value in px, got #{unit($px)}' - 定义基准变量如
$vw-base: 750(匹配 750px 设计稿),避免散落在多处 - 返回值必须是带单位的数值:
@return math.div($px, $vw-base) * 100vw(注意用sass:math替代旧除法)
哪些属性坚决不该用 vw() 转换
vw 是视口相对单位,只对“内容尺寸”类属性有效,对“描边类”属性天然不友好。
- 明确排除
border、outline、box-shadow、text-shadow—— 它们需物理像素一致性 - 字体大小慎用:
12px转vw后在 iPad Pro 上可能达 32px,建议配合clamp(12px, 4vw, 16px)或媒体查询设下限 -
transform: translateX(10px)不该转 —— 手势拖拽会因缩放抖动
vh 必须换成 dvh,且 fallback 不可省略
100vh 在 iOS/安卓软键盘弹出时仍按初始视口计算,导致底部按钮被遮挡。这不是 bug,是规范行为 —— vh 锚定 layout viewport,而键盘改变的是 visual viewport。
- 优先用
height: 100dvh,它响应键盘、地址栏收起等所有动态变化 - 必须用
@supports not (height: 100dvh)包裹降级规则,比如回退到100vh+ JS 监听resize(记得防抖) - 别给
html或body设height: 100vh,iOS 易触发滚动异常;改用 wrapper div +min-height: 100dvh
真正跨端时,vw/vh 不是“写了就完事”的单位,而是需要配合单位校验、属性白名单、dvh 替代、以及运行时 fallback 的一整套约束链。最容易被忽略的是:函数不校验单位、描边类属性照转、vh 不降级——这三处出问题,基本等于放弃兼容性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











