Web InnoventixFreeCode

Duotone Clear Effect

Original · free

Duotone-washed image clears to colour on hover.

byWeb InnoventixReact + Tailwind
duotoneclearimageeffect
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-duotone-clear.json
imgfx-duotone-clear.tsx
"use client";

const PHOTOS = [
  {
    src: "/img/gallery/g07.webp",
    alt: "Sunlit mountain ridge fading into layered morning haze",
    caption: "Ridgeline, first light",
  },
  {
    src: "/img/gallery/g18.webp",
    alt: "Quiet city street with reflections after rain",
    caption: "Wet street, late evening",
  },
  {
    src: "/img/gallery/g25.webp",
    alt: "Close portrait of hands working at a wooden bench",
    caption: "Hands at the bench",
  },
];

export default function ImgfxDuotoneClear() {
  return (
    <section className="relative w-full overflow-hidden bg-white px-6 py-20 text-slate-900 sm:px-10 sm:py-28 dark:bg-slate-950 dark:text-slate-100">
      <style>{`
        .duoclear-fig {
          --duoclear-shadow: 79 70 229;   /* indigo-600 */
          --duoclear-light: 244 63 94;    /* rose-500  */
        }
        .duoclear-media img {
          filter: grayscale(1) contrast(1.08) brightness(0.96);
          transform: scale(1.03);
          transition:
            filter 620ms cubic-bezier(0.22, 1, 0.36, 1),
            transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        .duoclear-tint {
          background: linear-gradient(
            140deg,
            rgb(var(--duoclear-shadow)) 0%,
            rgb(var(--duoclear-light)) 100%
          );
          mix-blend-mode: color;
          opacity: 0.92;
          transition: opacity 560ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        .duoclear-lift {
          background: linear-gradient(
            140deg,
            rgb(var(--duoclear-shadow)) 0%,
            rgb(var(--duoclear-light)) 100%
          );
          mix-blend-mode: screen;
          opacity: 0.14;
          transition: opacity 560ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        .duoclear-fig:hover .duoclear-media img,
        .duoclear-fig:focus-within .duoclear-media img {
          filter: grayscale(0) contrast(1) brightness(1);
          transform: scale(1);
        }
        .duoclear-fig:hover .duoclear-tint,
        .duoclear-fig:focus-within .duoclear-tint {
          opacity: 0;
        }
        .duoclear-fig:hover .duoclear-lift,
        .duoclear-fig:focus-within .duoclear-lift {
          opacity: 0;
        }
        .duoclear-ring {
          transition: box-shadow 560ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        @media (prefers-reduced-motion: reduce) {
          .duoclear-media img,
          .duoclear-tint,
          .duoclear-lift,
          .duoclear-ring {
            transition: none !important;
          }
          .duoclear-media img {
            transform: none;
          }
        }
      `}</style>

      <div className="mx-auto flex max-w-6xl flex-col">
        <header className="mb-12 max-w-2xl">
          <p className="text-xs font-semibold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-400">
            Image effect / Duotone clear
          </p>
          <h2 className="mt-3 text-3xl font-semibold tracking-tight text-slate-900 sm:text-4xl dark:text-white">
            Washed in two tones, then true colour on touch
          </h2>
          <p className="mt-4 text-base leading-relaxed text-slate-600 dark:text-slate-400">
            Each frame rests under an indigo-to-rose duotone. Hover or focus a
            card and the tint dissolves, the grain relaxes, and the photograph
            returns to full colour.
          </p>
        </header>

        <ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
          {PHOTOS.map((photo, i) => (
            <li key={photo.src}>
              <figure
                tabIndex={0}
                aria-label={`${photo.caption} — hover or focus to reveal full colour`}
                className="duoclear-fig group relative block outline-none"
              >
                <div className="duoclear-ring relative overflow-hidden rounded-2xl shadow-sm ring-1 ring-slate-200 group-hover:shadow-xl group-focus-within:shadow-xl dark:ring-slate-800">
                  <div
                    className={`duoclear-media relative w-full ${
                      i === 2 ? "aspect-[4/5]" : "aspect-[4/3]"
                    }`}
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={photo.src}
                      alt={photo.alt}
                      loading="lazy"
                      draggable={false}
                      className="absolute inset-0 h-full w-full object-cover"
                    />
                    <div
                      aria-hidden="true"
                      className="duoclear-tint pointer-events-none absolute inset-0"
                    />
                    <div
                      aria-hidden="true"
                      className="duoclear-lift pointer-events-none absolute inset-0"
                    />
                  </div>

                  <figcaption className="flex items-center justify-between gap-3 bg-white/80 px-4 py-3 backdrop-blur dark:bg-slate-900/70">
                    <span className="text-sm font-medium text-slate-800 dark:text-slate-200">
                      {photo.caption}
                    </span>
                    <span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400 transition-opacity duration-500 group-hover:opacity-0 group-focus-within:opacity-0 dark:text-slate-500">
                      Hover to reveal
                    </span>
                  </figcaption>
                </div>
              </figure>
            </li>
          ))}
        </ul>
      </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 →