React Responsive Masonry
react-responsive-masonry is a lightweight React component library for creating responsive masonry layouts using CSS Flexbox. It provides two main components: `Masonry` for a static column count and `ResponsiveMasonry` for dynamically adjusting columns and gutters based on breakpoints. The current stable version is 2.7.2. Releases appear to be driven by bug fixes and minor feature enhancements rather than a strict cadence, with the last major update to v2.0.0 in 2020 introducing ES6 modules. Its key differentiator is its simplicity and reliance on flexbox, avoiding complex JavaScript layout algorithms for performance and ease of use, making it suitable for image galleries or card layouts where item order isn't strictly sequential.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'length')
cause This often occurs when `Masonry` is rendered without any children or its children prop is not an array-like structure.fixEnsure `Masonry` always receives valid React children (e.g., `<Masonry>{items.map(item => <div key={item.id}>{item.content}</div>)}</Masonry>`) or handles the empty state gracefully. -
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
cause This error typically indicates an incorrect import for `Masonry` or `ResponsiveMasonry` (e.g., trying to use a named import for `Masonry` which is a default export).fixCheck your import statements. `Masonry` should be imported as a default, and `ResponsiveMasonry` as a named import. Example: `import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry'`. -
Warning: Failed prop type: Invalid prop `children` of type `array` supplied to `Masonry`, expected a single React element.
cause This warning, though uncommon for this specific library, could arise if React's development mode mistakenly applies a stricter `children` propType check or if the library's internal `children` handling expects a specific format.fixWhile `Masonry` is designed for multiple children, if this specific error appears (which might indicate an unusual environment or library conflict), ensure children are wrapped in a fragment or array explicitly if required, though typically direct children are passed. Double-check your React version compatibility and ensure no other libraries are interfering with prop type validation.
Warnings
- breaking Version 2.0.0 restructured the package to include separate ES6, CommonJS, and UMD builds. While existing import paths *should* mostly work due to `package.json` configurations, developers might experience issues if their build tools do not correctly resolve the new module entry points, especially in older environments.
- gotcha The `Masonry` component is a default export, while `ResponsiveMasonry` is a named export. Misunderstanding this can lead to 'is not a function' or 'undefined' errors.
- breaking Prior to v1.2.0, `prop-types` was not explicitly listed as a peer dependency. In v1.2.0, `prop-types` was added to `peerDependencies`, and `react` was updated to `15.5`. If using an older React version (pre-15.5) or not having `prop-types` installed, you might encounter warnings or runtime errors related to prop validation.
Install
-
npm install react-responsive-masonry -
yarn add react-responsive-masonry -
pnpm add react-responsive-masonry
Imports
- Masonry
import { Masonry } from 'react-responsive-masonry'import Masonry from 'react-responsive-masonry'
- ResponsiveMasonry
import ResponsiveMasonry from 'react-responsive-masonry'
import { ResponsiveMasonry } from 'react-responsive-masonry' - Masonry, ResponsiveMasonry
const { Masonry, ResponsiveMasonry } = require('react-responsive-masonry');import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry'
Quickstart
import React from 'react';
import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry';
// Imagine these are your child components or elements
const ChildA = () => <div style={{ height: '100px', background: '#e0e0e0', margin: '5px' }}>Item A</div>;
const ChildB = () => <div style={{ height: '150px', background: '#d0d0d0', margin: '5px' }}>Item B</div>;
const ChildC = () => <div style={{ height: '80px', background: '#c0c0c0', margin: '5px' }}>Item C</div>;
const ChildD = () => <div style={{ height: '200px', background: '#b0b0b0', margin: '5px' }}>Item D</div>;
const ChildE = () => <div style={{ height: '120px', background: '#a0a0a0', margin: '5px' }}>Item E</div>;
const ChildF = () => <div style={{ height: '90px', background: '#909090', margin: '5px' }}>Item F</div>;
function App() {
return (
<div style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
<h1>Responsive Masonry Example</h1>
<ResponsiveMasonry
columnsCountBreakPoints={{ 350: 1, 750: 2, 900: 3, 1200: 4 }}
gutterBreakPoints={{ 350: "10px", 750: "15px", 900: "20px", 1200: "25px" }}
>
<Masonry gutter="10px">
<ChildA />
<ChildB />
<ChildC />
<ChildD />
<ChildE />
<ChildF />
{/* More children here */}
</Masonry>
</ResponsiveMasonry>
</div>
);
}
export default App;