悬停放大平移

悬停时图片放大,移动指针就能在图上平移,不用打开查看器也能看清细节。

  • CSS
  • 图片
  • 跟随指针
  • 收录于
沙丘细节,2 倍放大

AI 提示词

用 React 和 CSS 制作悬停放大并平移的图片。外框设置 overflow hidden 和固定宽高比,内部图片填满外框。pointermove 时把图片的 transform-origin 设为指针所在的百分比位置;pointerenter 时用 300ms、cubic-bezier(0.16, 1, 0.3, 1) 的 transform 过渡把图片放大到 2 倍。transform-origin 不做过渡,或只给 80ms 的短过渡,让平移紧跟指针。pointerleave 时缩回 1 倍。使用 cursor: zoom-in。外框可聚焦,键盘用户在 :focus-visible 时以中心放大。在 prefers-reduced-motion 下放大不做过渡。说明文字为“沙丘细节,2 倍放大”。

源代码

Demo.tsx
'use client'

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

export default function HoverZoomPan({ labels }: { labels: Record<string, string> }) {
  const onMove = (e: React.PointerEvent<HTMLElement>) => {
    const r = e.currentTarget.getBoundingClientRect()
    const scene = e.currentTarget.firstElementChild as HTMLElement
    scene.style.transformOrigin = `${((e.clientX - r.left) / r.width) * 100}% ${((e.clientY - r.top) / r.height) * 100}%`
  }

  return (
    <figure className={s.frame} tabIndex={0} onPointerMove={onMove}>
      <div className={s.scene} role="img" aria-label={labels.caption} />
      <figcaption className={s.caption}>{labels.caption}</figcaption>
    </figure>
  )
}
demo.module.css
.frame {
  --sky: oklch(80% 0.07 70);
  --dune-1: oklch(68% 0.13 55);
  --dune-2: oklch(56% 0.13 45);
  --dune-3: oklch(44% 0.11 40);
  --sun: oklch(95% 0.05 85);
  position: relative;
  width: min(300px, 100%);
  aspect-ratio: 16 / 10;
  margin: 0;
  overflow: hidden;
  border-radius: 14px;
  cursor: zoom-in;
}

.frame:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }

.scene {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 60% 30% at 70% 100%, var(--dune-3) 98%, transparent 100%),
    radial-gradient(ellipse 70% 34% at 20% 92%, var(--dune-2) 98%, transparent 100%),
    radial-gradient(ellipse 80% 40% at 60% 80%, var(--dune-1) 98%, transparent 100%),
    repeating-linear-gradient(170deg, transparent 0 6px, oklch(100% 0 0 / 0.06) 6px 7px),
    radial-gradient(circle at 26% 30%, var(--sun) 0 7%, transparent 7.5%),
    linear-gradient(var(--sky), var(--dune-1));
  transition: transform 300ms var(--ease-out), transform-origin 80ms linear;
}

.frame:hover .scene { transform: scale(2); }
.frame:focus-visible .scene { transform: scale(2); transform-origin: center; }

.caption {
  position: absolute;
  left: 10px;
  bottom: 8px;
  padding: 3px 8px;
  border-radius: 6px;
  background: oklch(0% 0 0 / 0.45);
  color: var(--stage-ink);
  font: 500 var(--text-xs) / 1.3 var(--font-body);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .scene { transition: none; }
}

投稿创意

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

你想投稿的是?

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