Web InnoventixFreeCode

Glass Card Effect

Original · free

The image sits behind a frosted-glass caption card.

byWeb InnoventixReact + Tailwind
glasscardimageeffect
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-glass-card.json
imgfx-glass-card.tsx
"use client";

import { useRef } from "react";
import { motion, useInView, useReducedMotion } from "motion/react";

export default function ImgfxGlassCard() {
  const reduce = useReducedMotion();
  const ref = useRef<HTMLDivElement>(null);
  const inView = useInView(ref, { once: true, margin: "-15% 0px" });

  const rise = {
    hidden: { opacity: 0, y: reduce ? 0 : 28 },
    show: {
      opacity: 1,
      y: 0,
      transition: { duration: 0.7, ease: [0.22, 1, 0.36, 1] as const },
    },
  };

  return (
    <section className="relative w-full overflow-hidden bg-slate-100 py-20 px-6 sm:py-28 dark:bg-neutral-950">
      <style>{`
        @keyframes gcard_sheen {
          0%   { transform: translateX(-120%) skewX(-18deg); opacity: 0; }
          18%  { opacity: 0.55; }
          60%  { opacity: 0.15; }
          100% { transform: translateX(230%) skewX(-18deg); opacity: 0; }
        }
        .gcard_shell:hover .gcard_sheen { animation: gcard_sheen 1.5s cubic-bezier(0.4,0,0.2,1) forwards; }
        .gcard_shell:hover .gcard_zoom  { transform: scale(1.06); }
        .gcard_zoom { transform: scale(1); transition: transform 900ms cubic-bezier(0.22,1,0.36,1); }
        .gcard_panel { transition: transform 600ms cubic-bezier(0.22,1,0.36,1); }
        .gcard_shell:hover .gcard_panel { transform: translateY(-6px); }
        @media (prefers-reduced-motion: reduce) {
          .gcard_shell:hover .gcard_sheen { animation: none; }
          .gcard_shell:hover .gcard_zoom  { transform: scale(1); }
          .gcard_shell:hover .gcard_panel { transform: none; }
          .gcard_zoom, .gcard_panel { transition: none; }
        }
      `}</style>

      <div className="mx-auto max-w-2xl">
        <motion.div
          ref={ref}
          variants={rise}
          initial="hidden"
          animate={inView ? "show" : "hidden"}
        >
          <p className="mb-3 text-xs font-semibold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-400">
            Image Effect
          </p>
          <h2 className="mb-8 text-2xl font-bold tracking-tight text-slate-900 sm:text-3xl dark:text-white">
            Frosted glass caption
          </h2>

          <div className="gcard_shell group relative overflow-hidden rounded-3xl shadow-2xl shadow-slate-900/20 ring-1 ring-slate-900/5 dark:ring-white/10">
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img
              src="/img/gallery/g14.webp"
              alt="Golden light spilling across a mountain ridge at dawn"
              loading="lazy"
              draggable={false}
              className="gcard_zoom aspect-[4/5] w-full object-cover sm:aspect-[3/4]"
            />

            {/* sheen sweep */}
            <span
              aria-hidden
              className="gcard_sheen pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-gradient-to-r from-transparent via-white/60 to-transparent opacity-0"
            />

            {/* readability wash */}
            <span
              aria-hidden
              className="pointer-events-none absolute inset-0 bg-gradient-to-t from-slate-950/40 via-transparent to-transparent"
            />

            {/* frosted glass caption card */}
            <div className="gcard_panel absolute inset-x-4 bottom-4 rounded-2xl border border-white/40 bg-white/25 p-5 shadow-lg shadow-slate-950/10 backdrop-blur-xl backdrop-saturate-150 sm:inset-x-6 sm:bottom-6 sm:p-6 dark:border-white/15 dark:bg-neutral-900/35">
              <div className="flex items-center gap-2">
                <span className="h-1.5 w-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400" />
                <span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-700 dark:text-slate-200">
                  Field Notes
                </span>
              </div>
              <h3 className="mt-2 text-lg font-semibold text-slate-900 sm:text-xl dark:text-white">
                First light on the ridge
              </h3>
              <p className="mt-1 text-sm leading-relaxed text-slate-700 dark:text-slate-300">
                Shot at 5:42 AM before the wind picked up. The glass panel keeps
                text legible over any photo.
              </p>
            </div>
          </div>

          <p className="mt-5 text-sm text-slate-500 dark:text-neutral-400">
            Hover the image — the caption lifts and light sweeps across the glass.
          </p>
        </motion.div>
      </div>
    </section>
  );
}

Dependencies

motion

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 →