It's Christmas, get a 30% OFF. Apply code XMAS at checkout.

← Back to all tutorials

How to create a masonry grid layout with Tailwind CSS and JavaScript

masonry layout
Published and written on Oct 21 2024 by Michael Andreuzza

Good Monday everyone! Today, we’re going to learn how to create a masonry grid layout using Tailwind CSS and JavaScript.

What is a masonry grid layout?

A masonry grid layout is a type of grid layout where items are arranged in a two-dimensional grid, but unlike a standard grid where items are placed in strict rows and columns, a masonry grid places items in a staggered fashion. This helps fill in the vertical gaps and makes the layout look more fluid and dynamic.

This technique is widely used for presenting image galleries or content-heavy websites because it provides a visually engaging, organized layout without wasting space. You’ll often see it on popular websites like Pinterest, Dribbble, and Behance.

Why JavaScript?

You might be wondering: why not just use CSS for this? Well, CSS does have a property for this layout, display: masonry;, which aims to solve this exact problem. However, as of now, it’s still an experimental feature. It is not fully supported across all browsers and lacks consistent performance, especially in responsive designs where content needs to adapt dynamically.

Why JavaScript is necessary:

Since native CSS display: masonry; is experimental, using JavaScript ensures that the grid layout works consistently across all browsers…

Let’s get started with the HTML structure

As you can see below, the HTML structure is simple. Instead of manually adding all the images, we’ll use a component to pass the images dynamically as props.

ID’s

  • id=“masonry-grid”: This is the HTML structure that will be used to create the masonry grid container. It’s important to note that this ID is used to target the masonry grid container. Classes
  • rounded-2xl: This is the class that will be used to add rounded corners to the images.
<div
  id="masonry-grid">
  {
    heroImages.map((imagePath) => (
      <img
        src={imagePath}
        class="rounded-2xl"
        alt="#_"
      />
    ))
  }
</div>

Let’s get started with the JavaScript

Now that we have the HTML ridiculously simple structure ready, let’s start writing the JavaScript part.

The variables

  • const masonryGrid = document.getElementById("masonry-grid");: This is the variable that will be used to target the masonry grid container.
  • const columnWidth = 300;: This is the variable that will be used to set the column width of the masonry grid.
  • const gap = 18;: This is the variable that will be used to set the gap between the images in the masonry grid.
const masonryGrid = document.getElementById("masonry-grid");
const columnWidth = 300;
const gap = 18;

The function to create the masonry grid

  • function createMasonryGrid(): This is the function that will be used to create the masonry grid.
  • const gridWidth = masonryGrid.offsetWidth;: This is the variable that will be used to get the width of the masonry grid.
  • const columns = Math.floor(gridWidth / columnWidth) || 1;: This is the variable that will be used to calculate the number of columns in the masonry grid.
  • masonryGrid.style.columnCount = columns.toString();: This is the line that will be used to set the column count of the masonry grid.
  • masonryGrid.style.columnGap = ${gap}px;: This is the line that will be used to set the column gap of the masonry grid.
  • masonryGrid.style.display = "block";: This is the line that will be used to set the display of the masonry grid.
  • masonryGrid.style.gridTemplateColumns = "";: This is the line that will be used to clear the grid template columns of the masonry grid.
  • masonryGrid.style.gridTemplateRows = "";: This is the line that will be used to clear the grid template rows of the masonry grid.
  • const items = Array.from(masonryGrid.children);: This is the line that will be used to get the children of the masonry grid.
  • items.forEach((item) => {: This is the line that will be used to iterate over the children of the masonry grid.
  • item.style.gridRowStart = "";: This is the line that will be used to clear the grid row start of the masonry grid.
  • item.style.gridColumnStart = "";: This is the line that will be used to clear the grid column start of the masonry grid.
  • item.style.breakInside = "avoid";: This is the line that will be used to set the break inside property of the masonry grid.
  • item.style.marginBottom = ${gap}px;: This is the line that will be used to set the margin bottom of the masonry grid.

Calling the function

  • createMasonryGrid();: This is the line that will be used to call the createMasonryGrid function.

Adding event listeners

  • window.addEventListener("resize", createMasonryGrid);: This is the line that will be used to add a resize event listener to the window.
  • window.addEventListener("load", createMasonryGrid);: This is the line that will be used to add a load event listener to the window.
window.addEventListener("resize", createMasonryGrid);
window.addEventListener("load", createMasonryGrid);

Creating a MutationObserver

  • const observer = new MutationObserver(createMasonryGrid);: This is the line that will be used to create a new MutationObserver object.
  • observer.observe(masonryGrid, {childList: true, subtree: true});: This is the line that will be used to observe the masonry grid.
const observer = new MutationObserver(createMasonryGrid);
observer.observe(masonryGrid, {
    childList: true,
    subtree: true
});

The full script

function createMasonryGrid() {
    const gridWidth = masonryGrid.offsetWidth;
    const columns = Math.floor(gridWidth / columnWidth) || 1;
    masonryGrid.style.columnCount = columns.toString();
    masonryGrid.style.columnGap = `${gap}px`;
    masonryGrid.style.display = "block";
    masonryGrid.style.gridTemplateColumns = "";
    masonryGrid.style.gridTemplateRows = "";
    const items = Array.from(masonryGrid.children);
    items.forEach((item) => {
        item.style.gridRowStart = "";
        item.style.gridColumnStart = "";
        item.style.breakInside = "avoid";
        item.style.marginBottom = `${gap}px`;
    });
}
const masonryGrid = document.getElementById("masonry-grid");
const columnWidth = 300;
const gap = 18;
function createMasonryGrid() {
    const gridWidth = masonryGrid.offsetWidth;
    const columns = Math.floor(gridWidth / columnWidth) || 1;

    masonryGrid.style.columnCount = columns.toString();
    masonryGrid.style.columnGap = `${gap}px`;

    masonryGrid.style.display = "block";
    masonryGrid.style.gridTemplateColumns = "";
    masonryGrid.style.gridTemplateRows = "";
    const items = Array.from(masonryGrid.children);
    items.forEach((item) => {

        item.style.gridRowStart = "";
        item.style.gridColumnStart = "";

        item.style.breakInside = "avoid";
        item.style.marginBottom = `${gap}px`;
    });
}

createMasonryGrid();

window.addEventListener("resize", createMasonryGrid);
window.addEventListener("load", createMasonryGrid);

const observer = new MutationObserver(createMasonryGrid);
observer.observe(masonryGrid, {
    childList: true,
    subtree: true
});

Conclusion

While we can’t create a masonry grid layout with CSS or Tailwind CSS alone, we can use JavaScript to create one, for now until have have green light to use CSS.

Hope you enjoyed this tutorial and have a great day!

/Michael Andreuzza

Did you like this tutorial? Please share it with your friends!

Unlock all themes for $199 for forever! Includes lifetime updates, new themes, unlimited projects, and support. No subscription needed.

— No subscription required!