居中聚焦轮播

左右滑动一排会吸附到中心的卡片,位于中间的卡片放大到完整尺寸,其余的向后退。

  • CSS
  • 卡片
  • 拖拽
  • 收录于
01黎明
02正午
03黄昏
04深夜
05风暴
左右滑动或横向滚动

AI 提示词

用原生滚动吸附和 CSS 滚动驱动动画制作居中聚焦的卡片轮播。轨道是一个横向 flex 行,设置 overflow-x: auto、scroll-snap-type: x mandatory,左右内边距为“轨道宽度的一半减去卡片宽度的一半”,让第一张和最后一张卡片也能到达中心。每张卡片设置 scroll-snap-align: center。用 animation-timeline: view(inline) 为每张卡片驱动 keyframe:0% 时 scale(0.8)、opacity 0.45,50% 时 scale(1)、opacity 1,100% 时回到 scale(0.8)、opacity 0.45,这样位于中心的卡片最大。把动画包在 @supports (animation-timeline: view()) 中,其他浏览器得到普通的吸附滚动行。视觉上隐藏滚动条,但保持轨道可通过键盘聚焦。在 prefers-reduced-motion 下去掉缩放,保留吸附。卡片文字为黎明、正午、黄昏、深夜、风暴。

源代码

Demo.tsx
'use client'

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

export default function SnapCarousel({ labels }: { labels: Record<string, string> }) {
  return (
    <div className={s.wrap}>
      <div className={s.track} tabIndex={0} role="region" aria-label={labels.carousel}>
        {labels.items.split('|').map((t, i) => (
          <div key={t} className={s.card} style={{ '--h': 30 + i * 60 } as React.CSSProperties}>
            <span className={s.n}>{String(i + 1).padStart(2, '0')}</span>
            <strong className={s.name}>{t}</strong>
          </div>
        ))}
      </div>
      <span className={s.hint}>{labels.hint}</span>
    </div>
  )
}
demo.module.css
.wrap {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  gap: 10px;
}

.track {
  --card: 120px;
  display: flex;
  gap: 12px;
  padding: 8px calc(50% - var(--card) / 2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.track::-webkit-scrollbar { display: none; }
.track:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }

.card {
  flex: none;
  display: grid;
  align-content: space-between;
  width: var(--card);
  height: 150px;
  padding: 12px;
  border-radius: 14px;
  background: linear-gradient(160deg, oklch(64% 0.1 var(--h)), oklch(36% 0.06 var(--h)));
  scroll-snap-align: center;
}

.n { font: 500 var(--text-xs) / 1 var(--font-mono); color: oklch(100% 0 0 / 0.7); }
.name { font: 700 var(--text-xl) / 1 var(--font-display); color: oklch(98% 0.01 80); }

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

@supports (animation-timeline: view()) {
  .card {
    animation: focus linear both;
    animation-timeline: view(inline);
  }
}

@keyframes focus {
  0%, 100% { transform: scale(0.8); opacity: 0.45; }
  50% { transform: scale(1); opacity: 1; }
}

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

投稿创意

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

你想投稿的是?

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