piapia123
zh

CSS 3D 卡片翻转效果

样式

所有处理都在浏览器本地完成,数据不上传服务器

实时预览改上面的参数,这里立刻跟着变
CSS 代码

鼠标移上卡片,它翻过去露出背面。代码里有三个属性缺一不可,而它们也是最常被写错的地方,工具生成的代码里逐条标了出来: ① `perspective` 加在父层上,不是卡片自己身上 —— 它表示「眼睛离屏幕多远」。写在卡片自己身上是没有透视效果的(这是最常见的错法),结果翻转看起来是「压扁了」而不是「转过去」。② `transform-style: preserve-3d` 加在卡片上 —— 不加的话两个面会被压平成一个平面,翻转看起来像换个颜色。③ `backface-visibility: hidden` 加在两个面上 —— 否则背面是穿透可见的,转到一半会看到镜像的字。 另外背面要先自己转 180 度:两个面叠在同一个位置,背面不预先转过去的话,卡片转 180 度后看到的还是正面的内容。 最后一点实践建议:这个效果不适合放在信息密集的地方。翻转的过程会短暂遮住两面的内容,而且它在触屏上没有 hover,得靠点击或加类名触发。所以它最适合少量、独立的卡片(名片、产品卡、翻牌记忆游戏)。

功能

  • 绕 Y 轴(左右)或 X 轴(上下)翻转
  • 时长与透视距离可调 —— 透视越小,翻转的「压缩感」越强
  • 卡片尺寸可调,预览即时反映
  • 悬停预览区即可看到翻转过程
  • 交付的代码里三个关键属性逐条注明,并解释了每个为什么必需
  • 预览里正反两面都标了字,一眼看出转到哪一面
  • 自动附上 `prefers-reduced-motion` 的处理
  • 所有计算在浏览器本地完成

使用方法

  1. 选翻转轴:左右翻(rotateY)最常用,上下翻(rotateX)适合卡片列表
  2. 调透视距离 —— 900px 上下比较自然,小于 400 会明显夸张
  3. 调时长,界面上的翻转一般 400–900ms 比较舒服
  4. 把鼠标移到预览上看效果,然后复制代码

常见问题

为什么翻转看起来是「压扁」而不是「转过去」?
几乎肯定是 `perspective` 写错地方了。它必须加在卡片的父元素上(代码里的 `.flip-scene`),而不是卡片本身。写在卡片上时,浏览器不会给这个变换提供透视,于是绕 Y 轴旋转 90 度就变成「宽度压到 0」,看起来像被压扁了。这是这个效果最常见的一处错,而它的表现很有辨识度:翻转过程中卡片会变成一条线。
为什么转到一半能看到镜像的字?
因为漏了 `backface-visibility: hidden`。两个面是重叠在同一个位置的(都 `inset: 0`),没有这一条时,元素的背面也照样渲染 —— 转到 90 度之后再往后,你看到的是背面的「反面」,也就是镜像的字。加上这一条,元素背对观察者时整块隐藏,于是任意时刻只有一面可见。两个面都要加,只加一个还是会露。
触屏上怎么触发翻转?
`hover` 在触屏上不可靠(有些浏览器会把它当作「第一次点击」)。所以交付的代码里同时给了加类名的写法:`.flip-card.is-flipped`。用 JavaScript 在点击时切换这个类即可 —— 这也顺带解决了键盘用户的访问问题(把类名切换挂在按钮的点击与回车事件上,`Enter` 也能翻)。如果想要更稳妥,直接把它做成一个真正的按钮元素。
翻转的时长该取多少?
界面上的翻转一般 400–900ms。太短(小于 300ms)看不清转过去的过程,会显得突兀;太长(大于 1 秒)用户会等着它转完。另外要注意内容可读性:翻转过程中两面的内容都是斜的、不可读的,所以卡片上的关键信息不应该只有一面有 —— 或者让用户能靠点击保持住某一面,而不是必须按住悬停。

相关工具