Web InnoventixFreeCode

Swing Effect

Original · free

Image swings on a pivot on hover.

byWeb InnoventixReact + Tailwind
swingimageeffect
Open

Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.

npx shadcn@latest add https://webinnoventix.com/r/imgfx-swing.json
imgfx-swing.tsx
"use client";

export default function ImgfxSwing() {
  return (
    <section className="relative w-full bg-neutral-50 px-6 py-20 dark:bg-neutral-950 sm:py-28">
      <style>{`
        .imgfx-swing-card {
          transform-origin: 50% -12px;
          transform: rotate(0deg);
          transition: transform 900ms cubic-bezier(0.22, 1, 0.36, 1);
          will-change: transform;
        }
        .imgfx-swing-pivot:hover .imgfx-swing-card,
        .imgfx-swing-pivot:focus-visible .imgfx-swing-card {
          animation: imgfx-swing-oscillate 2600ms cubic-bezier(0.36, 0, 0.66, 1) 1;
        }
        @keyframes imgfx-swing-oscillate {
          0%   { transform: rotate(0deg); }
          12%  { transform: rotate(9deg); }
          30%  { transform: rotate(-6.5deg); }
          46%  { transform: rotate(4.2deg); }
          62%  { transform: rotate(-2.6deg); }
          78%  { transform: rotate(1.4deg); }
          90%  { transform: rotate(-0.6deg); }
          100% { transform: rotate(0deg); }
        }
        @media (prefers-reduced-motion: reduce) {
          .imgfx-swing-card {
            transition: none;
          }
          .imgfx-swing-pivot:hover .imgfx-swing-card,
          .imgfx-swing-pivot:focus-visible .imgfx-swing-card {
            animation: none;
          }
        }
      `}</style>

      <div className="mx-auto flex max-w-2xl flex-col items-center text-center">
        <p className="text-xs font-semibold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-400">
          Image Effect
        </p>
        <h2 className="mt-3 text-3xl font-semibold tracking-tight text-neutral-900 dark:text-neutral-50 sm:text-4xl">
          Pendulum Swing
        </h2>
        <p className="mt-3 max-w-md text-sm text-neutral-500 dark:text-neutral-400">
          A photo hung from a single pin. Hover to set it swinging, then watch it
          settle back to rest.
        </p>

        <div className="mt-16 flex justify-center">
          <div
            tabIndex={0}
            role="img"
            aria-label="A framed landscape photograph that swings from a pivot pin when hovered."
            className="imgfx-swing-pivot group relative rounded-full outline-none"
          >
            {/* pivot pin */}
            <span
              aria-hidden="true"
              className="absolute left-1/2 top-0 z-20 h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full bg-neutral-300 shadow-[inset_0_1px_2px_rgba(0,0,0,0.35)] ring-2 ring-neutral-400/60 dark:bg-neutral-600 dark:ring-neutral-500/60"
            />

            {/* hanging card */}
            <div className="imgfx-swing-card relative">
              {/* cords */}
              <span
                aria-hidden="true"
                className="absolute -top-3 left-1/2 z-10 h-6 w-px -translate-x-1/2 bg-gradient-to-b from-neutral-400/80 to-transparent dark:from-neutral-500/80"
              />
              <div className="relative overflow-hidden rounded-2xl border border-neutral-200/80 bg-white p-2.5 shadow-xl shadow-neutral-900/10 dark:border-neutral-800 dark:bg-neutral-900 dark:shadow-black/40">
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src="/img/gallery/g14.webp"
                  alt="Sunlit landscape photograph hanging in a frame"
                  loading="lazy"
                  draggable={false}
                  className="h-72 w-64 select-none rounded-lg object-cover sm:h-80 sm:w-72"
                />
                <p className="pt-2.5 text-center text-xs font-medium text-neutral-500 dark:text-neutral-400">
                  Hover to swing
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

Dependencies

None (React + Tailwind only).

Licence

Built by Web Innoventix. Free for personal and commercial use, no attribution required.

Built by Web Innoventix

Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.

Get a free quote

Similar components

Browse all →