button:active 伪类需配合默认状态下的 transition 才有过渡效果,否则为瞬时切换;移动端需解决 300ms 点击延迟问题,推荐用 pointer 事件手动控制按压态,并慎用 scale、避免 border-radius 过渡。

button:active 伪类必须配合 transition 才有过渡效果
直接写 button:active { transform: translateY(2px); } 不会动——因为没声明过渡属性。CSS 过渡只响应可动画的属性变化,且必须在「非 :active 状态」上定义 transition,否则浏览器认为这是瞬间切换。
-
transition要写在默认状态(比如button或button:not(:active)),不能只写在:active里 - 推荐只过渡
transform和background-color,避免触发布局重排;别用top/left或margin - 移动端需加
touch-action: manipulation防止点击延迟导致 :active 失效
移动端 click 延迟会让 :active 看不见
iOS Safari 和部分安卓浏览器默认有 300ms 点击延迟,:active 样式往往刚闪一下就没了,用户根本感知不到“按下”。这不是代码写错了,是浏览器行为。
- 加
meta name="viewport" content="width=device-width, initial-scale=1, touch-action: manipulation"是基础 - 更可靠的是用
pointerdown+pointerup+pointercancel手动控制 class(比如is-pressed) - 若用框架(React/Vue),优先监听
onPointerDown而非onClick来触发视觉反馈
transform: scale() 比 translateY() 更符合物理直觉
真实按钮被按下去,不只是往下移,还会轻微收缩、边缘变实——单靠 translateY() 显得“漂”。
- 推荐组合:
transform: translateY(1px) scale(0.98),再配box-shadow: inset 0 1px 3px rgba(0,0,0,0.2) - scale 要慎用:如果按钮内有文字或图标,缩得太狠(如
scale(0.9))会导致文字模糊,建议控制在0.97–0.99区间 - 别对
border-radius做过渡——它无法硬件加速,会掉帧
不要依赖 :active 模拟长按反馈
:active 只在鼠标按下/手指按住期间生效,松开立刻还原。想实现“按住 500ms 后变色”,它做不到。
立即学习“前端免费学习笔记(深入)”;
- 长按检测必须用 JS:
setTimeout监听pointerdown,并在pointerup/pointercancel中 clearTimeout - 用
will-change: transform提前告知浏览器该元素要动画,但仅在复杂界面中必要,日常按钮不用加 - 如果按钮是
disabled状态,:active完全不触发——记得单独定义button:disabled:active(虽然通常也不需要动)










