按钮按下时应通过 transform: translateY(2px) 和 box-shadow 的 offset-y、spread-radius 增加实现自然按压效果,避免使用 top、margin 或 blur 变化以防重排;transition 仅作用于 transform 和 box-shadow,时长控制在 0.12s,且需排查 :active 失效的三大原因(pointer-events、遮挡、type=submit 刷新)。

按钮按下时阴影变深 + 向下位移,但别卡顿
直接用 transform: translateY(2px) 配合 box-shadow 变化就能实现,关键不是“能不能动”,而是动得自然、不闪、不抖。浏览器对 transform 和 opacity 的优化最好,但一旦混进 top、margin 或改 box-shadow 的模糊半径(blur),就可能触发重排或低效重绘。
实操建议:
- 只用
transform做位移(推荐translateY(1px)~translateY(3px),别超 4px,否则像掉下去) -
box-shadow只调offset-y和spread,别碰blur—— 模糊值变化无法硬件加速 - 必须加
transition,且只写生效属性:transition: transform 0.12s ease, box-shadow 0.12s ease - 别在
:active里写will-change: transform—— 短暂状态没必要,反而可能引发渲染抖动
:active 状态失效?检查这三处
点了没反应,大概率不是 CSS 写错,而是被更高优先级的样式压制,或事件没落到按钮上。
常见错误现象:
立即学习“前端免费学习笔记(深入)”;
- 父容器有
pointer-events: none,或者按钮被遮挡(比如伪元素盖住) - 用了
button但 type 为submit,表单提交导致页面刷新,动效一闪而过 - CSS 中
:active写在了:hover后面,又被后者覆盖(顺序很重要)
使用场景:移动端尤其容易失效 —— iOS Safari 默认要等 touchend 才触发 :active,可加 * { -webkit-tap-highlight-color: transparent } 辅助,但更稳的是补 JS 监听 touchstart/touchend 切换 class。
阴影变深 + 位移的 box-shadow 写法细节
box-shadow 的四个数值顺序是 offset-x offset-y blur-radius spread-radius color,按下时想“看起来更重”,核心是加大 offset-y(往下压)和 spread-radius(让影子更实、不虚)。
对比示例:
button {
box-shadow: 0 2px 6px -2px rgba(0,0,0,0.15), 0 1px 2px -1px rgba(0,0,0,0.1);
}
button:active {
box-shadow: 0 4px 8px -2px rgba(0,0,0,0.25), 0 2px 3px -1px rgba(0,0,0,0.15);
transform: translateY(2px);
}注意点:
- 两层
box-shadow都保留负的blur-radius(如-2px),能抑制边缘发虚,压感更强 - 按下时第二层 shadow 的
offset-y和spread-radius要同步增加,否则像影子“拉长”而不是“压紧” - 别用
inset阴影模拟按压 —— 它和transform组合会视觉冲突,显得按钮被挖进去而不是按下
兼容性与性能陷阱:Safari 和低配安卓机
Safari 对 transform + box-shadow 连续过渡偶尔抽风,低配安卓 WebView 更倾向跳帧。这不是写法错,是渲染管线限制。
能做的妥协:
- 把
transition-duration控制在0.1s~0.15s,太慢(>0.2s)易感知卡顿,太快( - 避免在按钮上叠加
filter: drop-shadow()—— 它和box-shadow同时存在会强制软件渲染 - 如果项目需支持 Android 4.x 或旧版 UC,干脆放弃
:active动效,用 JS class 切换 +requestAnimationFrame控制,更可控
最常被忽略的一点:动效再细,也得确保按钮本身有足够点击热区(至少 44×44px),否则用户根本点不准,所有阴影位移都白搭。


















