Back to Dictionary
Waiting & Loading
●○○Ready to Use
Recommended default

Image Lazy Load Fade

Images load as low-res blurs or empty blocks and gently crossfade into their full high-resolution versions instead of popping in jarringly line-by-line.

Use

Image-heavy galleries

Avoid

Critical text content or SVGs that load instantly

Safer Alternative

No safer default listed.

Risk Level

Low risk

Live Demo

Loading...
Abstract art

What It Is

Images load as low-res blurs or empty blocks and gently crossfade into their full high-resolution versions instead of popping in jarringly line-by-line.

When to Use

  • Image-heavy galleries
  • E-commerce product grids

When NOT to Use

  • Critical text content or SVGs that load instantly

Configuration Tips

  • 01Keep the fallback background a soft gray or extract the dominant color of the image

You've Seen It In

MediumPinterestUnsplash

AI Implementation Prompts

Move from a fast scaffold to production details, then tune timing and edge states.

Add a lazy loading fade effect to all images on this grid.

Reference Implementation

The same implementation approach used by the live preview, kept compact enough to inspect and adapt.

"use client";
import { motion, AnimatePresence } from 'framer-motion';
import { useState, useEffect } from 'react';

export function ImageLazyLoadFadeDemo({ isPlaying = false }: { isPlaying?: boolean }) {
    const [isLoaded, setIsLoaded] = useState(false);

    useEffect(() => {
        if (!isPlaying) {
            setIsLoaded(false);
            return;
        }
        setIsLoaded(false);
        const timer = setTimeout(() => setIsLoaded(true), 1200);

        "text-stone-400 italic">// Loop it every 3.5 seconds
        const loop = setInterval(() => {
            setIsLoaded(false);
            setTimeout(() => setIsLoaded(true), 1200);
        }, 3500);

        return () => {
            clearTimeout(timer);
            clearInterval(loop);
        };
    }, [isPlaying]);

    return (
        <div className="flex h-64 w-full items-center justify-center overflow-hidden rounded-2xl bg-white p-4 shadow-sm ring-1 ring-stone-200">
            <div className="relative w-48 h-48 rounded-xl overflow-hidden bg-stone-100 flex items-center justify-center shadow-inner">
                {"text-stone-400 italic">/* Low res blur / skeleton placeholder */}
                <AnimatePresence>
                    {!isLoaded && (
                        <motion.div
                            className="absolute inset-0 bg-stone-200/50 backdrop-blur-md z-10 flex items-center justify-center"
                            initial={{ opacity: 1 }}
                            exit={{ opacity: 0 }}
                            transition={{ duration: 0.6 }}
                        >
                            <span className="text-stone-400 text-xs tracking-widest uppercase font-medium">Loading...</span>
                        </motion.div>
                    )}
                </AnimatePresence>

                {"text-stone-400 italic">/* High res image */}
                <motion.img
                    src="https:">//images.unsplash.com/photo-1618005182384-a83a8bd57fbe?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80"
                    alt="Abstract art"
                    className="object-cover w-full h-full"
                    initial={{ filter: "blur(10px)", scale: 1.05 }}
                    animate={{
                        filter: isLoaded ? "blur(0px)" : "blur(10px)",
                        scale: isLoaded ? 1 : 1.05
                    }}
                    transition={{ duration: 0.8, ease: "easeOut" }}
                />
            </div>
        </div>
    );
}