多层 box-shadow 必须整串存为语义化变量(如 --elevation-2),带引号、逗号分隔、单位齐全;顺序影响层叠(左底层→右顶层);真机 Safari 低电量模式会静默降级,建议≤4层且模糊≤10px、alpha≥0.12。

box-shadow 多层变量必须整串存储,不能拆参数拼接
浏览器不支持运行时字符串拼接,calc(var(--blur) + "px") 是非法语法,整条 box-shadow 声明会直接失效。你改了 --shadow-blur,但若 box-shadow 里没用 var(--shadow-blur),或者用了却漏单位(比如写成 2 而非 2px),阴影就彻底消失。
正确做法是把每套多层阴影当一个完整值存进语义化变量:
-
--elevation-2存"0 2px 4px rgba(0,0,0,0.08), 0 4px 12px rgba(0,0,0,0.06)",带引号包裹,逗号分隔 - 调用时只写
box-shadow: var(--elevation-2),简洁且可 fallback - 深色模式下重定义
--elevation-2即可,不用动其他变量
多层阴影顺序错了,立体感就塌了
多层 box-shadow 按逗号分隔的顺序从左到右绘制:第一个在最底层,最后一个在最顶层。很多人误以为“后写的在上”,结果把大光晕写在后面,被前面的小实影盖住,看起来像没生效。
模拟左上光源的真实层序示例:
立即学习“前端免费学习笔记(深入)”;
- 先写浅色高光:
2px -2px 4px rgba(255,255,255,0.3)(最底层) - 再写主投影:
4px 4px 12px rgba(0,0,0,0.12)(中层) - 最后加内阴影或锐利高光:
inset 0 -2px 4px rgba(255,255,255,0.2)(最顶层)
真机 Safari 在低电量模式下会悄悄降级模糊值或丢弃后几层,所以别堆超过 4 层。
JS 动态更新 --elevation-N 变量要避开三个坑
用 document.documentElement.style.setProperty('--elevation-2', newValue) 更新时,常见错误有:
- 值里漏引号:传
"0 4px 12px rgba(0,0,0,0.15)"合法;传0 4px 12px rgba(0,0,0,0.15)(无引号)会解析失败 - 单位不统一:混用
2px和2,后者不被识别为长度,导致整条失效 - 移动端 touchmove 坐标没适配:iOS Safari 的
e.touches[0].clientX才是真实坐标,e.clientX可能为 0
动态改完立刻生效,不需要 requestAnimationFrame 或强制重排——setProperty 本身已优化。
真机阴影变淡不是你变量写错了,是浏览器主动降级
iOS Safari 和部分安卓 WebView 在检测到模糊半径 > 10px 或层数 > 3 时,会静默压缩 alpha 值、降低渲染精度,甚至跳过某几层。DevTools 里看着正常,真机一跑就发灰。
上线前务必实测常用组合:
-
0 4px 8px rgba(0,0,0,0.12)—— 安全阈值,多数机型都稳 - 避免
rgba(0,0,0,0.05)这类极低透明度,旧 Android WebView 会四舍五入成 0 - 强一致性需求可换
filter: drop-shadow(),但它不支持inset
复杂点在于:你得同时兼顾设计稿的视觉张力、真机的渲染策略、以及用户是否开着低电量模式——这些没法靠变量自动适配,只能靠实测卡死边界值。


















