Creating visually appealing layouts is key to delivering a great user experience on the web, and one of the most popular styles historically has been the masonry layout. This layout is used on websites like Pinterest, where items are arranged in a grid, but unlike traditional grids, the items vary in height and flow into the spaces below them, much like bricks in a masonry wall.
In this article, I'll explore how to create a masonry-style layout using pure CSS, with no additional JavaScript required. This is not only more efficient but also ensures faster load times and a simpler codebase overall.
What is a Masonry Layout?
A masonry layout refers to a grid design where items are arranged in columns of different heights, fitting together like puzzle pieces without fixed row heights. This is perfect for showcasing content that varies in size, such as a gallery of images or blog posts with differing amounts of text.
And it gets its name from the way that mason's lay brick on a wall, typically with differing sized bricks layed side by side with minimal gaps in between them.
Why Use Masonry
There's a few reasons to consider a masonry layout, particularly if you're rendering multiple 'card-like' elements to a user and each one contains varying amounts of content:
Efficient use of space: Masonry layouts allow for the optimal use of vertical space without any awkward gaps. Again, particularly helpful if you have elements of different heights.
Flexible and responsive: This layout can adapt easily to different screen sizes.
Aesthetic appeal: The staggered arrangement gives a fresh, dynamic look compared to traditional grid layouts.
Traditional Approach: JavaScript and Masonry.js
Before the introduction of modern CSS properties (like flex and grid), achieving a masonry effect was usually done using JavaScript libraries like Masonry.js. And many developers, like myself, built out complicated scripts that measured content height and adjusted pixels accordingly. While effective, these solutions introduced extra dependencies, affecting page load speeds and increasing development complexity.
Thanks to advancements in CSS, you can now achieve this effect natively without relying on JavaScript, making for a cleaner and more efficient solution.
Key CSS Techniques for a Masonry Layout
To build a masonry layout using CSS, there are two main approaches:
CSS Grid Layout
CSS Columns Property, both of which I will break down below:
1. Masonry Layout with CSS Grid
CSS Grid is a powerful layout system that allows you to define rows and columns, but it can also be used to display items in a masonry style by using the grid-auto-flow property.
Here’s how you can implement a masonry layout with CSS Grid:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 10px;
gap: 10px;
}
.masonry-item {
background-color: #f2f2f2;
border-radius: 5px;
padding: 10px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
.masonry-item:nth-child(2n) {
grid-row: span 20;
}
.masonry-item:nth-child(odd) {
grid-row: span 15;
}
</style>
<title>CSS Masonry Layout</title>
</head>
<body>
<div class="masonry">
<div class="masonry-item">Item 1</div>
<div class="masonry-item">Item 2</div>
<div class="masonry-item">Item 3</div>
<div class="masonry-item">Item 4</div>
<div class="masonry-item">Item 5</div>
<div class="masonry-item">Item 6</div>
</div>
</body>
</html>
Let's break down what the CSS is doing above:
Grid template columns: We define a flexible grid with auto-fill, meaning the columns will fill the available space, and each column will have a minimum width of 200px.
Grid auto rows: The grid-auto-rows property is set to a small value (e.g., 10px), and then we use the grid-row span to adjust the height of each item based on its content.
Gap: The gap property creates the spacing between items.
This approach allows for a responsive masonry layout that fills the available space and adapts as you resize the browser. And it looks something like the following:
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
2. Masonry Layout with CSS Columns
Another popular way to create a masonry layout is by using the columns property. This method works similarly to how newspaper columns function, where content flows vertically into each column before moving on to the next.
Here's a quick example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.masonry-columns {
columns: 3; /* Number of columns */
column-gap: 10px; /* Gap between columns */
}
.masonry-item {
break-inside: avoid; /* Prevent items from breaking inside columns */
background-color: #f2f2f2;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
<title>CSS Masonry Layout with Columns</title>
</head>
<body>
<div class="masonry-columns">
<div class="masonry-item">Item 1</div>
<div class="masonry-item">Item 2</div>
<div class="masonry-item">Item 3</div>
<div class="masonry-item">Item 4</div>
<div class="masonry-item">Item 5</div>
<div class="masonry-item">Item 6</div>
</div>
</body>
</html>
Columns property: The columns CSS property is used to define the number of columns. You can set this to a fixed value (e.g., columns: 3), or let it automatically adjust based on the container width using columns: auto.
Column gap: The space between the columns is controlled using the column-gap property.
Break inside avoid: This ensures that each item remains intact and doesn’t split between columns.
This method is simpler than CSS Grid and may perform slightly better for basic layouts, but it lacks the fine-grained control over grid sizing and placement that CSS Grid offers.
And here is what that would look like:
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Responsive Design Considerations
Both approaches, CSS Grid and CSS Columns, can be made responsive by using media queries. For example, you can reduce the number of columns or adjust the grid configuration on smaller screens.
Here’s how you can modify the CSS Grid example to be more responsive:
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-auto-rows: 10px;
gap: 10px;
}
@media (max-width: 768px) {
.masonry {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
}
For the CSS Columns example, you can adjust the number of columns as the screen size changes:
.masonry-columns {
columns: 3;
column-gap: 10px;
}
@media (max-width: 768px) {
.masonry-columns {
columns: 2;
}
}
@media (max-width: 480px) {
.masonry-columns {
columns: 1;
}
}
Pros and Cons of Each Method
Both methods shown above will render the appropriate mason design exactly the same, but here are a few pro's and cons for each:
CSS Grid
Pros: Highly customizable, responsive, and works well with varying item sizes.
Cons: Slightly more complex to set up and requires modern browser support.
CSS Columns
Pros: Easy to implement, simple for basic layouts, and great for text-heavy content.
Cons: Limited control over the placement of items, and uneven columns can occur with varying item heights.
Conclusion
Creating a masonry layout using CSS is much easier today thanks to modern CSS properties like grid and columns. Both methods have their unique strengths, and the best approach will depend on your specific layout requirements.
For projects that need more control and flexibility, CSS Grid is the way to go. However, if you need a quick and simple solution for items that don’t require precise positioning, the columns method is an excellent alternative.