Pixelate reveal
Also called pixel reveal, depixelate animation, pixelated image loading, or Pixel Image
An entrance where an image first appears as large blocks of color and sharpens in steps, each with smaller pixels, until it reaches full resolution.
import { useEffect, useRef, useState } from 'react';
import { useInView, useReducedMotion } from 'motion/react';
const BLOCKS = [48, 24, 12, 6, 3]; // px per block, coarse to fine
const STEP_MS = 140;
type PixelateImageProps = {
src: string;
alt: string;
width: number;
height: number;
delay?: number;
};
export function PixelateImage({
src,
alt,
width,
height,
delay = 0
}: PixelateImageProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const inView = useInView(canvasRef, { once: true, amount: 0.4 });
const reduceMotion = useReducedMotion();
const [done, setDone] = useState(false);
useEffect(() => {
const context = canvasRef.current?.getContext('2d');
if (!inView || !context || reduceMotion) return;
const image = new Image();
const small = document.createElement('canvas');
let step = 0;
let timer = 0;
image.onload = () => {
timer = window.setInterval(() => {
const block = BLOCKS[step++];
if (block === undefined) {
window.clearInterval(timer);
return setDone(true);
}
// Drawing tiny averages the colors; scaling up without smoothing
// turns each tiny pixel into a sharp square.
const [w, h] = [Math.ceil(width / block), Math.ceil(height / block)];
small.width = w;
small.height = h;
small.getContext('2d')?.drawImage(image, 0, 0, w, h);
context.imageSmoothingEnabled = false;
context.drawImage(small, 0, 0, w * block, h * block);
}, STEP_MS);
};
const start = window.setTimeout(() => (image.src = src), delay);
return () => {
window.clearTimeout(start);
window.clearInterval(timer);
};
}, [inView, reduceMotion, src, width, height, delay]);
return (
<div
className='relative overflow-hidden rounded-xl bg-muted'
style={{ width, height }}
>
<canvas
ref={canvasRef}
width={width}
height={height}
aria-hidden
className='absolute inset-0'
/>
{/* The real image takes over for the last, sharp frame. */}
<img
src={src}
alt={alt}
width={width}
height={height}
className={`relative size-full object-cover ${done || reduceMotion ? '' : 'invisible'}`}
/>
</div>
);
}Reveal each gallery image with a pixelate effect when it scrolls into view: on a canvas, draw it in 5 steps with block sizes of 48px, 24px, 12px, 6px, and 3px, holding each for 140ms. For each step, draw the image into a tiny offscreen canvas and scale it back up with imageSmoothingEnabled = false. Then swap in the real img element. Stagger the images by 280ms, and show the sharp images immediately when prefers-reduced-motion is set.
Paste into Layerwise or any AI coding tool.
What is Pixelate reveal?
A pixelate reveal draws an image at a tiny size, then scales it back up without smoothing, so each tiny pixel becomes a visible square. Every step halves the block size, for example 48px, 24px, 12px, and 6px, and then the real image takes over. The jumps are the point: it looks like a retro game or a slow download catching up.
The usual build is a <canvas>. Draw the image into a small offscreen canvas, which averages the colors for you, then draw that canvas onto the visible one at full size with imageSmoothingEnabled = false. For a plain image, CSS image-rendering: pixelated gives the same blocky look when a small image is stretched. End by swapping in the real <img>, so the final frame is sharp and has alt text.
Use it for galleries, pixel art, game sites, avatars, and playful loading states. Keep the whole reveal under a second, about 100 to 200ms per step, and stagger a grid by a step or two per image. The steps flash, so show the finished image right away for people who prefer reduced motion.
Often confused with
- Blur in
- A blur in sharpens smoothly out of a soft blur. A pixelate reveal sharpens in visible steps, from big square blocks to full detail.
Related terms
All termsBlur in
An entrance animation where text or an image starts blurred and transparent, then sharpens into focus as it appears.
Reveal animation
An entrance where a moving edge uncovers an element, as if a curtain slides away, usually built with an animated clip-path.
Stepped animation
An animation that jumps through a set number of frames instead of moving smoothly, made with the CSS steps() timing function.
Lazy loading
A technique that waits to load images, videos, or code until they are about to scroll into view, so the first screen loads faster.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.


