react-responsive-masonry

A lightweight React masonry grid built with pure CSS flexbox — no JS layout engine, no image preloading, no dependencies beyond prop-types.

Library
npm
v2.7.2
455stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
41/100Fair
Development Activity8
Maintenance20
Community56
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture68
Code Quality55
Innovation45
Learning Curve80

react-responsive-masonry gives React apps a Pinterest-style masonry grid without pulling in a heavyweight layout engine. It ships two components — Masonry, which distributes children across a fixed number of columns using flexbox, and ResponsiveMasonry, which wraps it and swaps the column count and gutter size at configurable pixel breakpoints as the browser resizes.

Internally, Masonry measures each child’s rendered height via refs after the initial mount, then greedily assigns items to whichever column currently has the smallest total height — a classic shortest-column-first packing heuristic, recomputed only when children or column count change (guarded by shouldComponentUpdate and getDerivedStateFromProps to avoid needless re-renders). An optional sequential prop skips this height-based redistribution and keeps items in their original document order, trading a slightly less even layout for full control over ordering.

Because it depends only on prop-types and does no DOM measurement beyond getBoundingClientRect, it’s a reasonable fit for teams that want masonry layout without adopting a full grid/virtualization library, and it ships CJS, ESM, and UMD builds plus first-party TypeScript declarations.

What You Get

  • Masonry component that packs children into N flexbox columns using a shortest-column-first height-balancing algorithm
  • ResponsiveMasonry wrapper that changes columnsCount and gutter at configurable pixel breakpoints as the window resizes
  • A sequential prop to opt out of height-based reordering and preserve original child order
  • Customizable container/item tags (containerTag, itemTag) and inline style/itemStyle/className overrides
  • First-party TypeScript type declarations (types/index.d.ts) alongside CJS, ESM, and UMD builds
  • No layout dependencies beyond prop-types — no image-preloading, virtualization, or measurement libraries pulled in

Common Use Cases

  • Image/photo galleries where items have varying aspect ratios and a Pinterest-style grid looks better than a uniform grid
  • Blog or portfolio card layouts where content height varies per card and columns should stay visually balanced
  • Product or media listing pages that need to reflow from 1 to 3+ columns as the viewport narrows or widens
  • Any React UI needing masonry layout without adopting a larger grid/virtualization library as a dependency

Under The Hood

Architecture The library is two independent components composed together rather than one monolith. Masonry (src/Masonry/index.js) is a class component that owns the column-packing logic: getDerivedStateFromProps rebuilds an equal-count column split and a ref per child whenever children or columnsCount change, then componentDidUpdate triggers distributeChildren(), which waits until every child ref reports a measured height (via getBoundingClientRect) and only then performs one greedy pass — assigning each child to the column with the current minimum total height. ResponsiveMasonry (src/ResponsiveMasonry/index.js) is a separate functional component that tracks window.innerWidth through a resize-listener hook (guarded with useIsomorphicLayoutEffect for SSR safety), derives the active columnsCount/gutter from sorted breakpoint maps, and injects those values into its Masonry child via React.cloneElement — so the two components only interact through props, not shared internal state. If the core distributeChildren height-balancing pass changed, the entire rebalancing behavior for every consumer would change at once, since there’s no alternate packing strategy plugged in elsewhere. Tech Stack The runtime dependency surface is deliberately minimal: prop-types for the only runtime dependency, react/react-dom as peer dependencies (built and tested against React 16), and nwb as the build tool producing CommonJS, ES module, and UMD bundles plus the hand-authored TypeScript declaration file in types/. There’s no bundler config beyond nwb.config.js, no CSS-in-JS or external styling library — all layout is done via inline style objects using flexbox properties (display: flex, gap, flex: 1), so the only stylesheet dependency at runtime is the browser’s own CSS engine. Code Quality Tests live alongside each component (Masonry/index.test.js, ResponsiveMasonry/index.test.js) and use Jest with Enzyme’s mount plus the React 16 adapter — a testing stack that predates React’s official Testing Library recommendation, and coverage is limited to a couple of smoke-render assertions (default render, custom container/item tags) rather than testing the height-balancing algorithm itself. ESLint plus Prettier are wired through .eslintrc.js/.prettierrc and enforced pre-commit via Husky and lint-staged, and commitlint enforces conventional commit messages, but there is no CI badge currently passing beyond a Travis config that predates the repo’s more recent activity, and prop validation relies on runtime PropTypes rather than compile-time enforcement in the JS source itself (the .d.ts file is maintained separately by hand). What Makes It Unique The distinguishing choice is doing masonry layout with plain flexbox and a runtime height-measurement pass instead of either (a) CSS Grid’s grid-template-rows: masonry (not broadly supported), or (b) absolute-positioning libraries that require knowing image dimensions upfront. The shortest-column-first greedy heuristic is a well-known bin-packing approximation, not a novel algorithm, and the library trades perfect packing optimality for simplicity and a near-zero dependency footprint — a reasonable but standard engineering tradeoff rather than a technical innovation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search