用 :active 伪类配合 transform: translateY() 和双层 box-shadow 可实现纯 CSS 3D 按压效果,关键在于阴影方向、位移与过渡同步:默认状态 box-shadow: 0 -2px 0 2px #fff, 0 3px 6px rgba(0,0,0,0.15),:active 状态为 0 -1px 0 1px #eee, 0 1px 3px rgba(0,0,0,0.1),并配以 transform: translateY(2px) 和 transition: transform 0.18s, box-shadow 0.18s。

直接用 :active 伪类配合 transform: translateY() 和多层 box-shadow 就能做出可信的 3D 按压效果,不需要 JS、不用 3D 变换库,关键在阴影方向、位移同步和过渡时机的配合。
为什么单用 background-color 改变没按压感
用户感知“按下”依赖深度变化,不是颜色切换。只改背景色会丢失物理反馈:没有下沉错觉、没有受压变形、没有光影收缩。浏览器默认的 :active 状态甚至可能加 outline 或 border,反而破坏立体结构。
-
outline和border在部分浏览器(如 Safari)中会自动出现,必须显式重置:outline: none、border: none - 移动端点击时若未设
-webkit-tap-highlight-color: transparent,会闪白覆盖整个按钮,中断视觉连贯性 - 仅靠
opacity或filter: brightness()会让按钮“发灰”或“褪色”,而非“被压进去”
box-shadow 必须写两层且顺序不能错
单层 box-shadow: 0 4px 6px rgba(0,0,0,0.2) 只会让按钮像贴纸一样浮在页面上。真正立起来需要模拟光源——顶部高光 + 底部投影,且高光必须写在前面,否则会被后写的深色投影盖住。
- 正确写法:
box-shadow: 0 -2px 0 2px #fff, 0 3px 6px rgba(0,0,0,0.15) - 第一段
0 -2px是负偏移,表示从按钮顶部边缘向上延伸的亮边;第二段0 3px是正偏移,表示底部扩散的暗影 - 移动端慎用大
blur值(如12px),模糊边界会吞掉点击热区,尤其在小屏上易误触
:active 中必须同时改 transform 和 box-shadow
按压是复合动作:元素下沉 + 投影压缩 + 高光弱化。三者不同步,效果就假。比如只加 translateY(2px) 不缩阴影,按钮像掉进坑里;只缩阴影不位移,又像被吸扁了。
立即学习“前端免费学习笔记(深入)”;
- 默认状态推荐:
transform: translateY(0); box-shadow: 0 -2px 0 2px #fff, 0 3px 6px rgba(0,0,0,0.15) -
:active状态应为:transform: translateY(2px); box-shadow: 0 -1px 0 1px #eee, 0 1px 3px rgba(0,0,0,0.1) -
transition必须写在默认状态,且只锁定这两个属性:transition: transform 0.18s, box-shadow 0.18s;写all容易拖慢文字颜色、渐变等无关变化
容易被忽略的质感细节
立体感藏在边缘和明度协同里,不是阴影越厚越好。很多实现失败,是因为忽略了渐变角度、圆角比例和文字阴影对整体体积感的加成。
- 渐变建议用
linear-gradient(145deg, #4f4f4f, #3d3d3d)模拟金属反光条纹,避免纯黑#000端点,加一点灰度更耐看 -
border-radius推荐6px或8px,超过12px易显臃肿,削弱棱角带来的“凸起”暗示 - 文字加
text-shadow: 0 1px 0 #fff让它“浮”在按钮表面;深色背景则换为0 -1px 0 #000



















