翻转卡片

卡片以 3D 方式翻转,露出背面的详细信息;再次点击翻回正面。

  • CSS
  • 卡片
  • 点击
  • 收录于

AI 提示词

用 CSS 3D 为 React 制作翻转卡片。卡片是一个带 aria-pressed 的 <button>,以支持键盘和屏幕阅读器。内部元素设置 transform-style: preserve-3d,并对 transform 设置 600ms、cubic-bezier(0.65, 0, 0.35, 1) 的过渡;按下时旋转 rotateY(180deg)。正反两面用 position absolute 叠放,设置 backface-visibility: hidden,背面预先旋转 rotateY(180deg)。按钮上设置 perspective: 900px。正面显示“咖啡乌”和“点击翻面”;背面显示“加糖的黑咖啡,浓郁香甜,不加奶。”和“再次点击翻回”。用 aria-hidden 对屏幕阅读器隐藏背对用户的那一面。在 prefers-reduced-motion 下改为 150ms 的两面淡入淡出,不做旋转。

源代码

Demo.tsx
'use client'

import { useState } from 'react'
import s from './demo.module.css'

export default function FlipCard({ labels }: { labels: Record<string, string> }) {
  const [flipped, setFlipped] = useState(false)

  return (
    <button type="button" className={s.card} aria-pressed={flipped} onClick={() => setFlipped(!flipped)}>
      <span className={s.inner}>
        <span className={`${s.face} ${s.front}`} aria-hidden={flipped}>
          <strong className={s.title}>{labels.title}</strong>
          <span className={s.hint}>{labels.front}</span>
        </span>
        <span className={`${s.face} ${s.back}`} aria-hidden={!flipped}>
          <span className={s.text}>{labels.back}</span>
          <span className={s.hint}>{labels.hint}</span>
        </span>
      </span>
    </button>
  )
}
demo.module.css
.card {
  width: 200px;
  height: 180px;
  padding: 0;
  border: 0;
  background: none;
  perspective: 900px;
  cursor: pointer;
}

.card:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; border-radius: 16px; }

.inner {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 600ms var(--ease-in-out);
}

.card[aria-pressed='true'] .inner { transform: rotateY(180deg); }

.face {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: space-between;
  padding: 18px;
  border-radius: 16px;
  text-align: left;
  backface-visibility: hidden;
}

.front { background: var(--stage-accent); color: var(--stage-accent-ink); }
.back { background: var(--stage-surface); border: 1px solid var(--stage-rule); color: var(--stage-ink); transform: rotateY(180deg); }

.title { font: 700 var(--text-2xl) / 1.1 var(--font-display); }
.text { font: 400 var(--text-sm) / 1.5 var(--font-body); }
.hint { font: 500 var(--text-xs) / 1.2 var(--font-mono); letter-spacing: 0.04em; opacity: 0.75; }

@media (prefers-reduced-motion: reduce) {
  .inner { transition: none; }
  .card[aria-pressed='true'] .inner { transform: none; }
  .face { transition: opacity 150ms linear; transform: none; }
  .card[aria-pressed='true'] .front, .card[aria-pressed='false'] .back { opacity: 0; }
}

投稿创意

看到想收录的动效或主题?简单描述一下,会打开一个预先填好的 GitHub Issue,确认后即可提交。

你想投稿的是?

需要 GitHub 账号,投稿内容会公开。