真实按钮凹陷需 transform: translateY(1px) 与 box-shadow: inset 协同,缺一不可;移动端需 touch-action: manipulation 触发 :active;文字凹陷用双层反向 text-shadow;inset 阴影宜微调为 inset 0 2px 3px rgba(0,0,0,0.15)。

button:active 里只改 box-shadow 不够用
单纯把 box-shadow 的 y 值从正变负(比如 0 4px 6px rgba(0,0,0,0.1) → 0 -2px 4px rgba(0,0,0,0.15)),视觉上只是“阴影往上跑”,不是“按钮被按进去”。真实凹陷需要两层配合:transform: translateY(1px) 让按钮物理位移,box-shadow: inset 提供暗部收缩感。缺一不可。
常见错误包括:
- 只加
inset阴影但没位移,按钮看起来像浮在半空发虚 - 位移量过大(如
translateY(3px)),导致和周围元素对不齐 - 忘记统一
border-width,:active时边框缩进引发布局抖动
移动端 :active 不触发?先检查 touch-action
iOS Safari 默认禁用 :active 伪类的瞬时样式,Android Chrome 有时延迟 300ms 才响应。最轻量的修复是给按钮加 touch-action: manipulation,它告诉浏览器这个区域只做点击/滑动,可提前激活 :active 状态。
别用 ontouchstart="" 这种老方案——它会污染 HTML 结构,且在现代 WebView 中已不必要。如果仍无效,再考虑 JS 方案:addEventListener('touchstart', e => e.target.classList.add('pressed')),但 CSS 优先。
立即学习“前端免费学习笔记(深入)”;
注意:不要在 :active 里写 filter 或 clip-path,这些会触发重排,移动端直接卡顿或忽略样式。
凹槽文字必须用双层反向 text-shadow
想让按钮文字也显凹陷,不能靠 text-shadow: inset(语法非法,整条失效)。正确写法是两层方向相反的阴影:text-shadow: -1px -1px 0 #fff, 1px 1px 0 rgba(0,0,0,0.4)。前者是左上高光,后者是右下暗影,顺序不能颠倒(高光必须在前)。
关键细节:
-
blur-radius必须显式写0,写成空缺或0.1px会导致 Safari 渲染异常 - 深色背景上,第二层别用纯黑,改用
rgba(0,0,0,0.4),否则边缘生硬 - 小字号(≤16px)建议高光层用
rgba(255,255,255,0.8),避免过曝 - hover 或 active 时,同步加大偏移量(如
-2px -2px/2px 2px),否则文字和容器凹陷不同步
inset 阴影参数容易调过头
很多人一上来就套用 inset 0 4px 8px rgba(0,0,0,0.3),结果按钮像被挖掉一块,失去按钮感。真正自然的凹陷是微妙的:inset 0 2px 4px rgba(0,0,0,0.15) 更稳妥。
原因在于光照逻辑——真实按钮被按下时,顶部受光减弱、底部阴影收窄,不是简单加厚内阴影。所以:
- y 偏移量建议用正数(如
2px),方向朝下,匹配按压方向 - 透明度比常态高
0.03–0.05即可,太高会失真 - 模糊值(第三个参数)按下态宜略减小,比如从
4px降到3px,强化“紧贴”感 - 别在
:active里改border-radius,圆角变化会让按钮像在缩放,破坏凹陷预期
真正难的不是写对某一行代码,而是让文字、容器、阴影、位移四者在 100ms 内协同变化——稍有不同步,用户就会觉得“卡”或者“假”。调试时建议关掉所有其他 transition,只留 box-shadow 和 transform,确认节奏一致后再加回 background-color 或 text-shadow。



















