CSS 阴影进阶:多层 box-shadow 怎么做出真实景深与分层阴影
单层 box-shadow 撑不起真实景深, 多层阴影叠加才是关键。这篇讲清分层阴影技巧, Material Design 高度怎么对应到具体阴影栈, 以及怎么生成可直接用的 CSS 代码。
CSS 阴影进阶:多层 box-shadow 怎么做出真实景深与分层阴影
很多人写 box-shadow 停在 0 2px 4px rgba(0,0,0,0.2) 这一层, 然后觉得阴影"看着假"。问题不在数值, 在层数。真实世界里一个抬起的卡片不是只投一道影子, 它同时挡住了来自不同方向、不同距离的光, 所以脚下有一圈很紧很深的接触阴影, 周围还有一圈散开的、浅的弥散阴影。单层 box-shadow 只能描述其中一种, 两种叠在一起才有景深。
单层为什么撑不起景深
单层阴影只有一组 X / Y / blur / spread / color。你想让它"既深又散"是做不到的:模糊大了, 整个影子糊成一团灰雾, 卡片像浮在烟上;模糊小了, 边缘锐利, 卡片像贴了一张黑纸。这是物理上的矛盾, 因为接触点的硬影和远处的软影本来就是两回事, 用一组参数没法同时表达。
解决办法是把它拆成两到三层, 每层只负责一种光:一层紧贴元素、偏移小、模糊小、alpha 高, 负责"贴地"的接触感;一层偏移中等、模糊中等, 负责主体的体积;再来一层偏移大、模糊很大、alpha 很低, 负责远处那圈几乎看不见但又不能没有的弥散光。
多层阴影叠加:一个真实的输入输出例
下面这段是分层阴影里很经典的一组, 你可以直接拿去用:
box-shadow:
0 1px 1px rgba(0, 0, 0, 0.11),
0 2px 2px rgba(0, 0, 0, 0.11),
0 4px 4px rgba(0, 0, 0, 0.11),
0 8px 8px rgba(0, 0, 0, 0.11),
0 16px 16px rgba(0, 0, 0, 0.11);
注意这里的规律:每一层的 Y 偏移和 blur 都是上一层的两倍, alpha 全部保持一致。靠近元素的那几层模糊小、覆盖范围窄, 颜色叠加后接触点最深;越往下偏移越大、模糊越大, 颜色摊薄到一片极浅的灰。五层叠完, 阴影从脚下到外缘有一条自然的浓度渐变, 这是任何单层都做不出来的。同样的写法换成三层, 把指数从 1/2/4/8/16 改成 2/4/8 也行, 移动端我一般用三层, 桌面端 hero 卡片用五层。
Material Design 高度本质上就是分层阴影
Google 的 Material elevation 不是随手定的数值, 它把"元素抬起多少 dp"映射成一组固定的阴影栈。关键点:每一档 elevation 不是一层阴影, 而是三层的组合,一层近距离的关键光 (key light), 一层中距离的环境光 (ambient light), 一层远距离的弥散光。这正好对应上面说的"接触 + 体积 + 弥散"三段。所以你在层列表里看到一个 Material 预设占了三行, 不是工具多事, 是规范本来就这么定义的。
这也解释了为什么照着博客里某个"约等于"的单层值去抄 Material, 总觉得差一口气。差的就是那两层你没抄到的光。M2 时代 (Material Design 2) 这套 token 是公开且精确的, M1 到 M24 每一档都能查到准确的三层数值;M3 (Material You) 后来改用 tonal elevation, 拿 surface-tint 颜色代替阴影, 那是另一套体系, 没有干净的 box-shadow 等价物。
分层阴影的几个手感技巧
- alpha 不要平均分配。接触层可以到 0.18 到 0.24, 弥散层压到 0.04 以下, 中间过渡。整体观感比五层都用同一个 alpha 更通透。
- 颜色别用纯黑。纯黑阴影在彩色背景上发脏, 给阴影染一点和背景同色相、低饱和的深色, 卡片会"立"得更干净。
- 暗色背景要单独验证。一个在白底上拿捏得正好的阴影, 放到
#0a0e1a这种深色 hero 上常常直接消失。这时候得换思路, 要么改成发光式的浅色阴影, 要么靠分层里那道高 alpha 的接触影撑住边缘。 - 别用五层一模一样的阴影去"加深"。那只是 alpha 累加, 还白白增加绘制开销, 想更深直接调一层的 alpha 就够。多层是为了组合不同距离的光, 不是为了堆量。
我自己的工作流
我做卡片组件时基本不再手敲这些数字了。先在 CSS 阴影生成器 Pro 里挑一个最接近的 Material 档位当底, 它会把三层结构直接铺到层列表里;然后我逐层微调接触层的 alpha 和弥散层的偏移, 右边实时预览跟着动, 顺手切一下暗色背景看会不会糊掉。调到满意点导出 CSS 粘进组件, 全程一两分钟。以前在 DevTools 里盲调五层、改一个数刷新一次的日子, 是真的回不去了。
阴影常常不是单独出现的, 卡片的圆角、渐变底色会直接影响阴影看起来的味道。圆角越大, 内阴影越容易被边缘吃掉;底色是渐变时, 阴影的染色也得跟着走。配套调这两块可以用 渐变生成器, 把背景渐变先定下来, 再回头校阴影的颜色, 顺序对了能省一半返工。
把单层换成分层, 是 box-shadow 从"能用"到"像真的"之间那道坎。理解了接触、体积、弥散三段光, 再借 Material 的档位当参照, 你写出来的阴影就不再是糊在元素底下的一团灰, 而是真的把它从页面上抬了起来。
Made by Toolora · Updated 2026-06-13