Skip to content

Masonry Image Hover Grid

A CSS-columns masonry gallery with a scale + caption reveal on hover.

Freeeditorialminimal
Category
Assets
Added
2026-08-24
Deps
1
Updated
2026-08-24
Preview
Editorial
Product
Brand
Motion

Props

This entry takes no configurable props.

No runtime dependencies
"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>
  );
}
Notes

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.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

New

A row of panels where the hovered one grows and its neighbours compress.

hoveraccordiongallery
Featured
NewPro

A list of text rows, each hiding a photograph that wipes open under the cursor and follows it.

galleryhoverlist
Featured

A card grid with a soft red spotlight that follows the cursor across it.

gridspotlightcursor