多层 box-shadow 必须按“从底到顶”顺序书写,即扩散大、透明度低的阴影在前(底层),锐利高光或内阴影在后(顶层);变量值需加引号包裹,独立参数变量比字符串拼接更可控;真机和高对比度模式下阴影可能被降级或剥离,需针对性处理。

box-shadow 多层值必须按“从底到顶”顺序写进一个 var()
浏览器绘制多层 box-shadow 时,把逗号分隔的每一项当作一个图层,**第一个在最底层,最后一个在最顶层**。如果你把光晕(大而淡)写在后面,它会被前面的小而实的阴影盖住,看起来像没生效。用变量存多层阴影时,这个顺序不能靠 JS 或后期拼接修正——CSS 不解析字符串逻辑,只原样代入。
常见错误现象:--shadow: '0 0 30px rgba(0,0,0,0.05), 0 4px 12px rgba(0,0,0,0.1)',结果光晕完全不可见,因为第二层压住了第一层。
- 正确顺序:先写扩散最大、透明度最低的(底层),再写偏移小、对比稍强的(中层),最后是锐利高光或内阴影(顶层)
- 示例(模拟左上光源):
--shadow: '2px -2px 4px rgba(255,255,255,0.3), 4px 4px 12px rgba(0,0,0,0.08), 0 0 24px rgba(0,0,0,0.04)' - 所有值必须包裹在单引号或双引号里,否则空格和逗号会被截断成多个无效 token
拆解参数变量比拼接字符串更稳,但别滥用 calc() 拼单位
想动态改某一项(比如 hover 时只加大模糊值),用独立变量如 --shadow-blur 比维护一整条字符串更可控。但 CSS 不支持运行时字符串拼接,calc(var(--shadow-blur) + "px") 是非法语法,会直接失效。
真正能用的组合方式只有这一种:box-shadow: var(--shadow-x) var(--shadow-y) var(--shadow-blur) var(--shadow-spread) var(--shadow-color)。
-
--shadow-x、--shadow-y等变量值必须自带单位(如4px),不能只写数字 - 如果要支持深色模式,
--shadow-color推荐用rgba()字符串(如rgba(0,0,0,0.12)),而不是分离 r/g/b/a 四个变量——后者会导致大量冗余计算且无法 fallback - 避免在
:root里定义未使用的中间变量,比如--shadow-temp,它们不会被 GC,纯属增加解析负担
移动端真机上阴影变淡?不是 bug,是浏览器主动降级
iOS Safari 和部分安卓 WebView 在检测到模糊半径 > 10px 或阴影层数 > 3 层时,会悄悄降低 alpha 值或跳过渲染——尤其在低电量模式下。DevTools 里看着正常,真机一跑就发灰。
这不是你变量写错了,而是硬件加速策略触发的静默降级。
- 上线前务必在真机 Safari / Chrome 中测试常用值,例如
0 4px 12px rgba(0,0,0,0.12) - 慎用
rgba(0,0,0,0.05)这类极低透明度:旧版 Android WebView 会四舍五入为 0,阴影直接消失 - 若必须保一致性,可用伪元素 +
filter: drop-shadow()替代,但注意它不支持inset,也不能响应 CSS 变量变化
高对比度模式(HC)下阴影自动消失,得用 @media (forced-colors: active) 特殊处理
Windows 高对比度或 macOS “增加对比度”开启时,浏览器会强制剥离所有 box-shadow 和 filter 效果。这是 WCAG 合规要求,不是 CSS 变量没生效。
依赖阴影表达层级或状态,在 HC 模式下等于失效。你得提前准备视觉替代方案。
- 必须加兜底媒体查询:
@media (forced-colors: active) { box-shadow: none; border: 2px solid CanvasText; } - 别指望 JS 检测
forced-colors然后动态加 class——该媒体查询是唯一可靠手段 - 测试时必须真机开启 HC 模式,
prefers-contrast查询无法触发真实降级行为
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











