Web InnoventixFreeCode

Diagonal Band Effect

Original · free

A diagonal caption band sweeps across the image on hover.

byWeb InnoventixReact + Tailwind
diagonalbandimageeffect
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-diagonal-band.json
imgfx-diagonal-band.tsx
"use client";

import { useState } from "react";

type Slide = {
  src: string;
  alt: string;
  eyebrow: string;
  caption: string;
};

const SLIDES: Slide[] = [
  {
    src: "/img/gallery/g07.webp",
    alt: "Sunlit ridgeline fading into layered morning haze",
    eyebrow: "No. 07",
    caption: "Ridgeline at first light",
  },
  {
    src: "/img/gallery/g19.webp",
    alt: "Quiet harbour reflecting a low amber evening sky",
    eyebrow: "No. 19",
    caption: "Harbour, slack water",
  },
  {
    src: "/img/gallery/g28.webp",
    alt: "Dense forest canopy seen from directly overhead",
    eyebrow: "No. 28",
    caption: "Canopy from above",
  },
];

export default function ImgfxDiagonalBand() {
  const [active, setActive] = useState(0);
  const slide = SLIDES[active];

  return (
    <section className="relative w-full bg-gradient-to-b from-zinc-50 to-white px-6 py-20 sm:py-28 dark:from-zinc-950 dark:to-black">
      <style>{`
        .idb-figure { --idb-band: 132%; }
        .idb-band {
          transform: translate(var(--idb-band), calc(-50% - var(--idb-band))) rotate(-24deg);
          transition: transform 620ms cubic-bezier(0.16, 1, 0.3, 1);
          will-change: transform;
        }
        .idb-figure:hover .idb-band,
        .idb-figure:focus-visible .idb-band,
        .idb-figure:focus-within .idb-band {
          transform: translate(0, -50%) rotate(-24deg);
        }
        .idb-caption {
          opacity: 0;
          transform: translateY(8px);
          transition: opacity 340ms ease 160ms, transform 340ms ease 160ms;
        }
        .idb-figure:hover .idb-caption,
        .idb-figure:focus-visible .idb-caption,
        .idb-figure:focus-within .idb-caption {
          opacity: 1;
          transform: translateY(0);
        }
        .idb-img {
          transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1), filter 700ms ease;
        }
        .idb-figure:hover .idb-img,
        .idb-figure:focus-visible .idb-img,
        .idb-figure:focus-within .idb-img {
          transform: scale(1.05);
          filter: saturate(1.08) brightness(0.94);
        }
        @media (prefers-reduced-motion: reduce) {
          .idb-band { transform: translate(0, -50%) rotate(-24deg); transition: none; }
          .idb-caption { opacity: 1; transform: none; transition: none; }
          .idb-img { transition: none; }
          .idb-figure:hover .idb-img,
          .idb-figure:focus-visible .idb-img,
          .idb-figure:focus-within .idb-img { transform: none; filter: none; }
        }
      `}</style>

      <div className="mx-auto max-w-2xl text-center">
        <p className="text-xs font-semibold uppercase tracking-[0.25em] text-indigo-600 dark:text-indigo-400">
          Image Effect
        </p>
        <h2 className="mt-3 text-2xl font-bold tracking-tight text-zinc-900 sm:text-3xl dark:text-zinc-50">
          Diagonal Caption Band
        </h2>
        <p className="mt-3 text-sm text-zinc-500 dark:text-zinc-400">
          Hover the frame and a titled band sweeps across the photo on the diagonal.
        </p>
      </div>

      <div className="mx-auto mt-12 max-w-lg">
        <figure
          className="idb-figure group relative aspect-[4/5] w-full overflow-hidden rounded-3xl bg-zinc-200 shadow-2xl shadow-zinc-900/10 ring-1 ring-zinc-900/10 outline-none dark:bg-zinc-800 dark:shadow-black/40 dark:ring-white/10"
          tabIndex={0}
          aria-label={`${slide.caption}. Hover or focus to reveal the caption band.`}
        >
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            key={slide.src}
            src={slide.src}
            alt={slide.alt}
            loading="lazy"
            draggable={false}
            className="idb-img absolute inset-0 h-full w-full object-cover"
          />

          {/* Diagonal sweeping band */}
          <div className="idb-band pointer-events-none absolute inset-x-[-30%] top-1/2 flex h-24 items-center justify-center bg-indigo-600/95 shadow-lg shadow-indigo-950/30 backdrop-blur-[1px] dark:bg-indigo-500/95">
            <div className="idb-caption flex flex-col items-center px-6 text-center">
              <span className="text-[0.65rem] font-semibold uppercase tracking-[0.3em] text-indigo-200">
                {slide.eyebrow}
              </span>
              <span className="mt-1 text-lg font-semibold tracking-tight text-white">
                {slide.caption}
              </span>
            </div>
          </div>

          {/* Idle hint, hidden once revealed */}
          <figcaption className="pointer-events-none absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full bg-black/45 px-3 py-1 text-[0.7rem] font-medium text-white/90 backdrop-blur-sm transition-opacity duration-300 group-hover:opacity-0 group-focus-within:opacity-0">
            Hover to reveal
          </figcaption>
        </figure>

        {/* Slide selector */}
        <div className="mt-6 flex items-center justify-center gap-3">
          {SLIDES.map((s, i) => (
            <button
              key={s.src}
              type="button"
              onClick={() => setActive(i)}
              aria-label={`Show ${s.caption}`}
              aria-pressed={i === active}
              className={`h-2.5 rounded-full transition-all duration-300 ${
                i === active
                  ? "w-8 bg-indigo-600 dark:bg-indigo-400"
                  : "w-2.5 bg-zinc-300 hover:bg-zinc-400 dark:bg-zinc-700 dark:hover:bg-zinc-600"
              }`}
            />
          ))}
        </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 →