Masonry Image Hover Grid
A CSS-columns masonry gallery with a scale + caption reveal on hover.
- Category
- Assets
- Added
- 2026-08-24
- Deps
- 1
- Updated
- 2026-08-24
Props
This entry takes no configurable props.
"use client";
import { motion } from "framer-motion";
type Tile = { src: string; label: string };
export function MasonryImageHoverGrid({ tiles, columns = 3 }: { tiles: Tile[]; columns?: number }) {
return (
<div className={`columns-${columns} gap-2.5`} style={{ columnCount: columns }}>
{tiles.map((tile) => (
<motion.div
key={tile.src}
tabIndex={0}
whileHover="hover"
whileFocus="hover"
className="group relative mb-2.5 overflow-hidden rounded-xl break-inside-avoid outline-none focus-visible:ring-2 focus-visible:ring-red-500"
>
<motion.img
src={tile.src}
alt={tile.label}
variants={{ hover: { scale: 1.08 } }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
className="w-full"
/>
<motion.div
variants={{ hover: { opacity: 1, y: 0 } }}
initial={{ opacity: 0, y: 8 }}
transition={{ duration: 0.2 }}
className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/60 to-transparent px-3 py-2"
>
<span className="text-sm font-semibold text-white">{tile.label}</span>
</motion.div>
</motion.div>
))}
</div>
);
}
About this asset
A true masonry layout needs items of different heights to stack without gaps, and CSS grid can't do that without precomputing row-spans; CSS multi-column (columns-N) does it natively, with break-inside-avoid keeping each tile from splitting across a column. The hover choreography — image scale-up and caption slide-fade together — runs off Framer's variant propagation: the parent sets whileHover="hover" once, and every child that declares a matching hover variant animates in sync, no per-child hover listener duplicating the trigger. Reach for CSS columns over grid when images have real, varying aspect ratios you don't want to precompute; reach for grid instead when the design needs strict row-aligned reading order, because column layout fills top-to-bottom within each column first, not left-to-right across a row — so the visual order for someone scanning left-to-right won't match the source array order the way a row-based grid would. The component ships with no default tiles; a consumer supplies the array and picks the column count.
Curator’s note
Uses CSS columns rather than CSS grid for the masonry flow — grid requires manually computing row-spans to avoid gaps between variable-height items, while columns lets the browser flow items into balanced columns natively.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Expanding Panel Row
patternsA row of panels where the hovered one grows and its neighbours compress.
Hover Reveal Text Gallery
patternsA list of text rows, each hiding a photograph that wipes open under the cursor and follows it.
Spotlight Card Grid
patternsA card grid with a soft red spotlight that follows the cursor across it.