box-shadow扩散本质是模糊半径与偏移量的渐变动画,需保持阴影层数一致、显式声明transition属性并兼顾可访问性与设备适配。

box-shadow 的扩散本质是模糊半径和偏移量的变化
所谓“阴影扩散”,不是阴影真的变大了,而是通过增大 blur-radius(模糊半径)让阴影边缘更松散、覆盖范围更广;同时常配合微调 offset-x 和 offset-y 让阴影看起来从卡片底部“浮起”。关键在于:起始和结束状态的 box-shadow 必须有可插值的数值维度,否则 transition 不会生效。
常见错误是只改颜色或只加一层新阴影而忽略旧值清空——CSS 不会自动“合并”或“替换”阴影,而是叠加。悬停后多出一层阴影,实际是两层共存,容易显得生硬或过重。
- 起始状态建议用单层、小 blur(如
0 2px 6px rgba(0,0,0,0.1)) - 悬停状态推荐增加 blur(如
0 8px 24px rgba(0,0,0,0.15)),保持 offset 为 0 或仅轻微上移(0 -2px 12px模拟上浮) - 务必在基础状态就声明
box-shadow,哪怕值为none,否则 transition 无法从“无”到“有”平滑过渡
transition 必须显式指定 box-shadow 才能生效
很多人写 transition: all 0.3s ease,看似省事,实则危险:它会让所有可动画属性一起动,包括 background-color、opacity 等,可能引发意外闪烁或性能抖动;更关键的是,某些浏览器对 all 中 box-shadow 的插值支持不稳定,尤其当阴影层数不一致时。
- 正确写法是锁定属性:
transition: box-shadow 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) - 时间选 0.25s–0.35s 较自然,太短像弹跳,太长显迟滞
- 缓动函数推荐
cubic-bezier(0.25, 0.46, 0.45, 0.94)(类似 Material Design 的标准浮起曲线),比ease更有“升腾感”
多层阴影叠加时 transition 会失效?这是计算逻辑问题
当你写 box-shadow: 0 2px 4px red, 0 4px 8px blue;,再在 hover 里写 box-shadow: 0 6px 12px purple;,浏览器不会“替换”而是“覆盖”——但 transition 只对同结构的阴影序列插值。两组阴影层数不同(2 层 vs 1 层),大多数浏览器直接跳变,不渐变。
- 解决办法:始终维持相同层数。例如基础态写两层,hover 态也写两层,只是第二层设为透明或极小值:
box-shadow: 0 2px 6px rgba(0,0,0,0.1), 0 0 0 rgba(0,0,0,0); - hover 时激活第二层:
box-shadow: 0 2px 6px rgba(0,0,0,0.1), 0 8px 24px rgba(0,0,0,0.15); - 这样两层都参与插值,扩散更连贯,且第二层从“不可见”到“可见”,视觉上就是“扩散出来”
移动端点击无响应?别忘了 focus-visible 和 prefers-reduced-motion
纯 :hover 在触摸设备上基本无效——手指点下去没有“悬停”概念。如果只靠 hover 实现扩散,iOS / Android 用户根本看不到效果。另外,系统开启“减少动画”偏好时,transition 默认仍会执行,可能违背用户意图。
- 补救方式:加上
:focus-within或:focus-visible,让键盘用户和部分触摸场景(如 Safari 点击后短暂聚焦)也能触发 - 尊重系统设置:用
@media (prefers-reduced-motion: reduce)把 transition 设为none或0.01s - 真实项目中,扩散阴影本质是装饰性动效,不是功能必需,别为了它牺牲可访问性或兼容性
最易被忽略的一点:阴影扩散的“度”没有标准值,blur-radius 加多少、偏移怎么配,取决于卡片本身尺寸、背景对比度、整体设计语言。小卡片配大阴影会喧宾夺主,深色背景上浅阴影可能完全看不见——得真正在目标设备上点一点、拖一拖,而不是只看代码预览。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











