Masonry grid layout using react-stack-grid with NextJS

Cover Image for Masonry grid layout using react-stack-grid with NextJS
toofancoder
toofancoder

If you want to head over to the code on Github, using react-stack-grid.

Using version as below

  • NextJS - 14.2.15
  • ReactJS - 18.0.0
  • react-stack-grid - ^0.7.1

I tried using react-stack-grid from react-stack-grid NPM Package but it took me some time to get this to work correctly. And that is why this blog post.

In modern web development, building responsive and dynamic layouts is key to delivering great user experiences. One handy library for creating masonry-style grid layouts in React is react-stack-grid. This component lets you easily build nextjs grid layouts that respond to screen sizes and realign items when the viewport changes.

In this blog post, I'll guide you through using react-stack-grid to create a grid layout in a Next.js project, showcasing how to integrate it into a simple gallery-style application.

Show me the code

Step 1: Setting up Next.js

Before we dive into react-stack-grid, let’s start with a basic Next.js setup. If you already have a Next.js app, you can skip this part.

To create a new Next.js app, run:

npx create-next-app@latest react-stack-grid-demo
cd react-stack-grid-demo

Step 2: Install react-stack-grid

Now, let's install react-stack-grid and its dependencies. Run the following command in your project directory:

npm install react-stack-grid

Step 3: Basic Usage of react-stack-grid

Once react-stack-grid is installed, we can create a simple gallery component to display images in a dynamic grid layout. Here's an example:

Create a new component Gallery.js under the components/ directory.

The gist of code in Gallery.js is as below

"use client";

import { SAMPLE_IMAGES } from "@/utils/constants";
import { useEffect, useState } from "react";
import StackGrid from "react-stack-grid";

export default function Gallery() {
  const [photoGrid, setPhotoGrid] = useState(null);

  useEffect(() => {
    // Not the best solution but this is what I found.
    // If you found a better solution, please
    // send a pull request on github
    const id = setTimeout(() => {
      if (photoGrid) {
        // until the images load, their width
        // and height is not determined.
        // This updates the grid layout
        // to show the images correctly
        // once they are fully loaded.
        photoGrid.updateLayout();
      }
      // tweak the time as needed
    }, 1000);

    return () => clearTimeout(id);
  }, [photoGrid]);

  return (
    <StackGrid
      columnWidth="23%"
      duration={0}
      gutterHeight={16}
      gutterWidth={16}
      gridRef={(grid) => setPhotoGrid(grid)}
    >
      {SAMPLE_IMAGES.map((src, index) => (
        <div
          key={index}
          style={{
            display: "flex",
            justifyContent: "center",
          }}
        >
          <img
            src={src}
            alt={`Gallery Image ${index}`}
            width={240}
            height={"auto"}
            onClick={() => {
              console.log("Image has been clicked");
            }}
          />
        </div>
      ))}
    </StackGrid>
  );
}

Conclusion

React Stack Grid provides a powerful and flexible solution for creating masonry-style layouts in Next.js applications. While there are some quirks to handle, particularly around image loading and layout updates, the library offers a straightforward way to implement responsive grid layouts with minimal code.

Key takeaways:

  • Easy integration with Next.js projects
  • Responsive grid layouts with customizable column widths and gutters
  • Handles dynamic content updates through the updateLayout() method
  • Works well with image galleries and card-based layouts

The solution presented here demonstrates how to handle common challenges like image loading delays and layout updates. While there's room for optimization, this implementation provides a solid foundation for building attractive, responsive grid layouts in your Next.js applications.

Remember to check out the complete example on GitHub for more details and implementation insights.