perspective必须设在外层容器而非按钮本身,值800px–1500px最稳;backface-visibility需分别作用于.front、.back和.flipper三层;transition须声明在.flipper默认样式中;移动端必须用js切换class而非:hover。

perspective 必须设在外层容器,不是按钮本身
直接写 .btn { perspective: 1200px; } 没用——浏览器根本不会触发 3D 渲染上下文。perspective 值必须加在翻转容器的**父级**上,比如 .btn-container,且该容器得有明确宽高(不能是 display: inline 或未设 width/height)。实测 800px~1500px 最稳,1200px 是按钮类场景的甜点值;移动端可放大到 1600px 避免小屏畸变。
常见错误:按钮带阴影时 perspective 太小(如 200px),阴影会被严重拉伸,出现肉眼可见的“撕裂感”;太大(如 5000px)又退化成平面旋转,失去纵深感。
backface-visibility: hidden 要写三层,漏一层就翻车
不是加一次就完事。它必须分别作用于:.front、.back 和包裹它们的翻转层(如 .flipper 或 .card)。漏掉任意一层,翻转到 90° 左右就会透出背面内容、文字镜像重叠,甚至双影。
尤其注意 .flipper 这一层:它是 transform 的执行主体,若没设 backface-visibility: hidden,其子元素的 3D 空间会被压平,transform-style: preserve-3d 就失效了。旧版 Safari(15.4 之前)还得补 -webkit-backface-visibility: hidden。
-
.front和.back是真正承载内容的节点,必须各自设 -
.flipper不渲染内容,但它是 3D 变换的锚点,不设就崩 - 别给
:before/:after单独设——它们依附宿主,宿主设了就行
transition 必须声明在常态样式里,不是 hover 里
写成 .btn-container:hover .flipper { transform: rotateY(180deg); transition: transform 0.6s; } 是错的。transition 得提前写在 .flipper 的默认样式中:.flipper { transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); }。否则首次 hover 会掉帧,动画卡顿。
用 cubic-bezier(0.4, 0, 0.2, 1) 替代 ease-out,收尾更自然;别对 perspective 或 transform-style 做 transition——它们不触发动画,只会白屏或闪动。
快速连 hover 时,transition 不会中断重置,移开鼠标自动回弹,无需 JS 干预。
移动端必须用 JS 切换 class,纯 :hover 不可靠
Safari 和多数安卓 WebView 中,:hover 在触摸设备上不触发或立即失效,导致卡片只闪一下就回弹。必须用 JS 控制状态:button.addEventListener('click', () => card.classList.toggle('is-flipped')),再靠 .card.is-flipped { transform: rotateY(180deg); } 覆盖默认值。
移动端还有三个硬性补救点:
– 用 <button></button> 标签,别用 <div>;<br>– 加 <code>ontouchstart=""(空值即可),绕过 300ms 延迟;
– 补 touch-action: manipulation,提前激活点击态。
真机测试必不可少——模拟器常无法还原实际持续时间与位移量,阴影书写顺序和 :active 的位移方向,物理直觉比代码更重要。











