Web InnoventixFreeCode

Crosshatch Effect

Original · free

A crosshatch texture overlays the image, fading on hover.

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

import { useReducedMotion } from "motion/react";

export default function ImgfxCrosshatch() {
  const reduce = useReducedMotion();

  return (
    <section className="relative w-full overflow-hidden bg-neutral-100 px-6 py-20 text-neutral-900 sm:py-28 dark:bg-neutral-950 dark:text-neutral-100">
      <style>{`
        @keyframes xhatch_inkbleed {
          from { opacity: 0; transform: translateY(14px) scale(0.985); }
          to   { opacity: 1; transform: translateY(0) scale(1); }
        }
        .xhatch-plate {
          --xhatch-fade: 1;
          animation: xhatch_inkbleed 720ms cubic-bezier(0.22, 1, 0.36, 1) both;
        }
        .xhatch-plate:hover { --xhatch-fade: 0; }
        .xhatch-plate:focus-visible { --xhatch-fade: 0; }
        .xhatch-veil {
          opacity: calc(var(--xhatch-fade) * 0.9);
          transition: opacity 620ms cubic-bezier(0.22, 1, 0.36, 1);
          background-image:
            repeating-linear-gradient(45deg,  rgba(23,23,23,0.34) 0 1px, transparent 1px 6px),
            repeating-linear-gradient(-45deg, rgba(23,23,23,0.34) 0 1px, transparent 1px 6px),
            repeating-linear-gradient(45deg,  rgba(23,23,23,0.20) 0 1px, transparent 1px 3px),
            repeating-linear-gradient(-45deg, rgba(23,23,23,0.20) 0 1px, transparent 1px 3px);
        }
        .xhatch-tone {
          opacity: calc(var(--xhatch-fade) * 0.28);
          transition: opacity 620ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        .xhatch-img {
          filter: saturate(calc(0.55 + (1 - var(--xhatch-fade)) * 0.45)) contrast(calc(1.06 - (1 - var(--xhatch-fade)) * 0.06));
          transform: scale(calc(1 + (1 - var(--xhatch-fade)) * 0.04));
          transition: filter 620ms cubic-bezier(0.22, 1, 0.36, 1), transform 720ms cubic-bezier(0.22, 1, 0.36, 1);
        }
        @media (prefers-reduced-motion: reduce) {
          .xhatch-plate { animation: none; }
          .xhatch-veil, .xhatch-tone, .xhatch-img { transition: none; }
        }
      `}</style>

      <div
        aria-hidden
        className="pointer-events-none absolute -left-24 top-10 h-64 w-64 rounded-full bg-amber-300/20 blur-3xl dark:bg-amber-500/10"
      />
      <div
        aria-hidden
        className="pointer-events-none absolute -right-16 bottom-0 h-72 w-72 rounded-full bg-indigo-300/20 blur-3xl dark:bg-indigo-500/10"
      />

      <div className="relative mx-auto flex max-w-4xl flex-col items-center">
        <div className="mb-10 text-center">
          <p className="text-[0.7rem] font-semibold uppercase tracking-[0.42em] text-amber-700 dark:text-amber-400">
            Image FX / Crosshatch
          </p>
          <h2 className="mt-4 font-serif text-4xl font-medium tracking-tight sm:text-5xl">
            Inked, then revealed
          </h2>
          <p className="mx-auto mt-4 max-w-md text-sm leading-relaxed text-neutral-600 dark:text-neutral-400">
            A hand-drawn crosshatch veil sits over the plate like an engraving.
            Hover to let the ink bleed away and the photograph surface.
          </p>
        </div>

        <figure
          tabIndex={0}
          className="xhatch-plate group relative aspect-[4/5] w-full max-w-md cursor-pointer overflow-hidden rounded-sm bg-neutral-200 shadow-2xl shadow-neutral-900/20 outline-none ring-1 ring-neutral-900/10 focus-visible:ring-2 focus-visible:ring-amber-500 dark:bg-neutral-900 dark:shadow-black/50 dark:ring-white/10"
          style={reduce ? { animation: "none" } : undefined}
        >
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            src="/img/gallery/g14.webp"
            alt="Portrait study rendered beneath a fading crosshatch engraving veil"
            loading="lazy"
            draggable={false}
            className="xhatch-img absolute inset-0 h-full w-full object-cover"
          />

          <div
            aria-hidden
            className="xhatch-tone absolute inset-0 bg-gradient-to-br from-neutral-50 to-neutral-300 mix-blend-multiply dark:from-neutral-700 dark:to-neutral-900"
          />
          <div aria-hidden className="xhatch-veil absolute inset-0 mix-blend-multiply dark:mix-blend-screen" />

          <div
            aria-hidden
            className="pointer-events-none absolute inset-0 ring-1 ring-inset ring-white/10"
          />

          <figcaption className="pointer-events-none absolute inset-x-0 bottom-0 flex items-end justify-between p-4">
            <span className="rounded-full bg-neutral-950/70 px-3 py-1 text-[0.65rem] font-medium uppercase tracking-[0.2em] text-neutral-100 backdrop-blur-sm">
              Plate No. 14
            </span>
            <span className="rounded-full bg-amber-400/90 px-3 py-1 text-[0.65rem] font-semibold uppercase tracking-[0.2em] text-neutral-950 opacity-0 transition-opacity duration-500 group-hover:opacity-100 group-focus-visible:opacity-100">
              Uninked
            </span>
          </figcaption>
        </figure>

        <p className="mt-6 text-xs font-medium uppercase tracking-[0.28em] text-neutral-500 dark:text-neutral-500">
          Hover or focus the plate
        </p>
      </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 →