光泽倾斜卡片

卡片会朝指针方向做 3D 倾斜,同时一块光斑在表面滑动,像真实的反光。

  • CSS
  • 卡片
  • 跟随指针
  • 收录于
会员工作室通行证有效期至 2027 年 12 月

AI 提示词

制作一个会朝指针做 3D 倾斜的 React 卡片,用 CSS 自定义属性驱动。在 pointermove 时,把指针位置换算成每个轴上 -0.5 到 0.5 的数值,并写入卡片的 --px 和 --py。在 CSS 中设置 transform: perspective(800px) rotateX(calc(var(--py) * -12deg)) rotateY(calc(var(--px) * 12deg)),并加上 150ms 的 ease-out 过渡。用 ::after 添加一层光泽:35% 不透明度的白色 radial-gradient,用相同的变量定位到指针处,并设置 mix-blend-mode: soft-light。pointerleave 时把两个变量重置为 0。在 prefers-reduced-motion 下禁用倾斜。卡片显示标签“会员”、标题“工作室通行证”和一行文字“有效期至 2027 年 12 月”。

源代码

Demo.tsx
'use client'

import s from './demo.module.css'

export default function TiltCard({ labels }: { labels: Record<string, string> }) {
  const onMove = (e: React.PointerEvent<HTMLDivElement>) => {
    const el = e.currentTarget
    const r = el.getBoundingClientRect()
    el.style.setProperty('--px', ((e.clientX - r.left) / r.width - 0.5).toFixed(3))
    el.style.setProperty('--py', ((e.clientY - r.top) / r.height - 0.5).toFixed(3))
  }

  const onLeave = (e: React.PointerEvent<HTMLDivElement>) => {
    e.currentTarget.style.setProperty('--px', '0')
    e.currentTarget.style.setProperty('--py', '0')
  }

  return (
    <div className={s.card} onPointerMove={onMove} onPointerLeave={onLeave}>
      <span className={s.kicker}>{labels.kicker}</span>
      <strong className={s.name}>{labels.name}</strong>
      <span className={s.meta}>{labels.meta}</span>
    </div>
  )
}
demo.module.css
.card {
  --px: 0;
  --py: 0;
  position: relative;
  display: grid;
  align-content: end;
  gap: 4px;
  width: min(260px, 100%);
  aspect-ratio: 1.6;
  padding: 20px;
  overflow: hidden;
  border-radius: 14px;
  background: var(--stage-surface);
  border: 1px solid var(--stage-rule);
  color: var(--stage-ink);
  transform: perspective(800px) rotateX(calc(var(--py) * -12deg)) rotateY(calc(var(--px) * 12deg));
  transition: transform 150ms var(--ease-out);
}

.card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    circle at calc((var(--px) + 0.5) * 100%) calc((var(--py) + 0.5) * 100%),
    var(--stage-sheen),
    transparent 55%
  );
  mix-blend-mode: soft-light;
  pointer-events: none;
}

.kicker {
  font: 500 var(--text-xs) / 1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--stage-muted);
}

.name {
  font: 600 var(--text-xl) / 1.2 var(--font-display);
}

.meta {
  font-size: var(--text-sm);
  color: var(--stage-muted);
}

@media (prefers-reduced-motion: reduce) {
  .card { transform: none; }
}

投稿创意

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

你想投稿的是?

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