When I first started building image-heavy dashboards in React, one of the biggest challenges I faced was organizing content in a clean, Pinterest-style grid layout.
I tried using plain CSS grid and Flexbox, but they didn’t quite give me that seamless, “waterfall” look I wanted. That’s when I discovered the react-masonry-component, and it changed everything.
In this tutorial, I’ll show you exactly how I use this library to create a beautiful, responsive Masonry layout in my React projects.
What Is a Masonry Layout?
A Masonry layout arranges elements optimally based on available vertical space. Think of the Pinterest feed; each item stacks neatly without leaving awkward gaps.
This type of layout is perfect for displaying:
- Image galleries
- Product listings
- Blog cards
- Dashboards or portfolios
In React, you can easily achieve this using the react-masonry-component library, which is a wrapper around the popular Masonry layout engine by David DeSandro.
Method 1 – Install and Set Up react-masonry-component
Before we begin, ensure you have Node.js and npm installed. Here’s how I usually set up a new React project with Masonry:
Step 1: Create a New React App
Open your terminal and run:
npx create-react-app react-masonry-demo
cd react-masonry-demoStep 2: Install react-masonry-component
Next, install the library:
npm install react-masonry-componentThis package is quite stable and works well with React 18+.
Method 2 – Create a Simple Masonry Layout
Now, let’s create our first Masonry layout. I’ll use a few sample images (you can replace them with your own). Here’s the full working code:
Full Example Code
src/App.js
import React from "react";
import Masonry from "react-masonry-component";
import "./App.css";
const masonryOptions = {
transitionDuration: 0,
gutter: 10,
};
const images = [
"https://source.unsplash.com/random/300x200?sig=1",
"https://source.unsplash.com/random/300x250?sig=2",
"https://source.unsplash.com/random/300x300?sig=3",
"https://source.unsplash.com/random/300x350?sig=4",
"https://source.unsplash.com/random/300x400?sig=5",
"https://source.unsplash.com/random/300x450?sig=6",
"https://source.unsplash.com/random/300x500?sig=7",
"https://source.unsplash.com/random/300x550?sig=8",
];
function App() {
return (
<div className="App">
<h1>My React Masonry Gallery</h1>
<Masonry
className={"my-gallery-class"}
elementType={"div"}
options={masonryOptions}
disableImagesLoaded={false}
updateOnEachImageLoad={false}
>
{images.map((src, index) => (
<div className="image-element-class" key={index}>
<img src={src} alt={`Gallery ${index}`} />
</div>
))}
</Masonry>
</div>
);
}
export default App;src/App.css
.App {
text-align: center;
padding: 20px;
background-color: #fafafa;
}
.my-gallery-class {
display: flex;
margin: auto;
justify-content: center;
}
.image-element-class {
margin-bottom: 10px;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.image-element-class img {
width: 100%;
display: block;
}I executed the above example code and added the screenshot below.

- The Masonry component automatically arranges your images in a cascading grid.
- The gutter option adds spacing between items.
- The layout adjusts dynamically as the images load.
When you run the app (npm start), you’ll see a beautiful, Pinterest-style layout in your browser.
Method 3 – Make It Responsive
By default, the Masonry layout adapts well to different screen sizes, but you can enhance responsiveness with CSS.
Here’s how I usually do it:
src/App.css (Add this below the existing CSS)
@media (max-width: 768px) {
.my-gallery-class {
display: block;
}
.image-element-class {
width: 100%;
}
}I executed the above example code and added the screenshot below.

This ensures that on smaller devices, images stack vertically for a clean mobile experience.
Method 4 – Add Dynamic Data (Optional)
You can also load images dynamically from an API, for example, from Unsplash or your own database.
Here’s a quick example using React’s useEffect and useState hooks:
import React, { useState, useEffect } from "react";
import Masonry from "react-masonry-component";
const masonryOptions = { transitionDuration: 0, gutter: 10 };
function DynamicMasonry() {
const [photos, setPhotos] = useState([]);
useEffect(() => {
fetch("https://api.unsplash.com/photos/random?count=10&client_id=YOUR_ACCESS_KEY")
.then((res) => res.json())
.then((data) => setPhotos(data))
.catch((err) => console.error(err));
}, []);
return (
<Masonry className="dynamic-gallery" options={masonryOptions}>
{photos.map((photo) => (
<div key={photo.id} className="image-element-class">
<img src={photo.urls.small} alt={photo.alt_description} />
</div>
))}
</Masonry>
);
}
export default DynamicMasonry;I executed the above example code and added the screenshot below.

This example fetches random images from Unsplash and displays them in a Masonry layout, perfect for dashboards or photo feeds.
Method 5 – Handle Image Loading Smoothly
Sometimes, images load at different speeds, which can cause layout jumps. The react-masonry-component has a built-in prop called imagesLoadedOptions that helps manage this.
Here’s how I use it:
<Masonry
className="my-gallery-class"
options={masonryOptions}
imagesLoadedOptions={{ background: ".image-element-class" }}
>
{/* image elements */}
</Masonry>I executed the above example code and added the screenshot below.

This ensures the layout updates only after all images are properly loaded, giving a smoother experience.
Bonus: Use Masonry with Material UI
If you’re already using Material UI, you can combine Masonry with MUI cards or grids for a polished look.
Example:
import { Card, CardMedia, CardContent, Typography } from "@mui/material";
import Masonry from "react-masonry-component";
function MUIStyledMasonry({ data }) {
return (
<Masonry options={{ gutter: 15 }}>
{data.map((item) => (
<Card key={item.id} sx={{ margin: "8px" }}>
<CardMedia component="img" height="200" image={item.image} alt={item.title} />
<CardContent>
<Typography variant="h6">{item.title}</Typography>
</CardContent>
</Card>
))}
</Masonry>
);
}This is great for e-commerce or portfolio websites where you want each item to have a card-like appearance.
Common Issues I’ve Encountered (and Fixed)
- Images overlapping:
Ensure each image has a fixed width or is contained within the same width container. - Layout not updating on new data:
Use the updateOnEachImageLoad prop set to true. - Performance issues with large datasets:
Lazy-load images or paginate your data to improve performance.
When I first used the react-masonry-component, it took me only a few minutes to set up, but it instantly elevated the look of my React projects.
Whether you’re building a photo gallery, a product showcase, or a portfolio, this library gives you a professional, responsive layout with minimal effort.
You may also like to read:
- How To Create a Navbar Component in React
- Difference between React Component and React Element
- Create a React Loading Spinner Component
- How to Use useRef in React Functional Components

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.