1. Web Design
  2. HTML/CSS
  3. HTML Templates

How to Build Seamless Masonry Layouts With CSS Grid and object-fit:cover

Scroll to top

CSS Grid makes developers’ lives easier, as it allows the creation of unique layouts effortlessly. In today’s tutorial we’ll use CSS Grid to build a responsive image grid that will follow a masonry-style layout on desktop screens.

Final product imageFinal product imageFinal product image
What You'll Be Creating

Our Image Masonry Layout

As usual, take a look at our finished project:

Be sure to check out the full screen version, and resize your browser window to notice how the layout changes depending on the screen size.

info
This is a 100% CSS masonry layout—no JavaScript necessary at all!

1. Decide Upon the Layout

Today’s demo is dedicated to Morocco. Our image grid will reveal the beauty of this fascinating country through 11 stunning Unsplash photos.

On screens up to 849px, we’ll have a two-column layout like this:

The image grid on small screensThe image grid on small screensThe image grid on small screens

As you can see, just to make the layout a bit more distinct, one of the images (the ninth one) will sit on its own row and be twice as large as the others.

On screens that are at least 850px, our images will sit inside a masonry layout like this:

The image grid on large screensThe image grid on large screensThe image grid on large screens

The real power of CSS Grid is that it gives us the ability to modify the above layout with just a few style modifications. For example, here’s another version of it:

An alternative version of the image gridAn alternative version of the image gridAn alternative version of the image grid

In the past, to build these kinds of layouts, developers had to use a JavaScript library like Masonry.js.

2. Define the HTML Markup

To develop this grid, all we need is an unordered list. Each image will live inside a list item.

Here’s the required structure:

1
<ul class="grid">
2
  <li>
3
    <figure>
4
      <img width="640" height="1138" src="morocco4.jpg" alt="">
5
    </figure>
6
  </li>
7
  <li>
8
    <figure>
9
      <img width="640" height="427" src="morocco1.jpg" alt="">
10
    </figure>
11
  </li>
12
  <!-- more items here  -->
13
</ul>

Consider how clean this markup is. CSS Grid is ideal for these types of layouts. If you try building it with another layout method like flexbox, you’ll have to insert nested elements. And most importantly, other solutions just aren’t flexible enough. To update the layout, you’ll need to restructure the markup and not just modify the styles.  

3. Specify the Main Styles

The best way to become familiar with our grid-related styles is by inspecting your browser console, targeting the unordered list, and checking the rows and columns using a grid inspector.

The grid linesThe grid linesThe grid lines

Here are the notable things regarding our styles:

  • The list will be our grid container. 
  • On small screens (<850px), as we said earlier, we’ll have a two-column layout. We’ll specify the size of the columns via the grid-template-columns property while we’ll use the grid-auto-rows property to set the size of the implicitly-created rows. 
  • On large screens (850px), we’ll have a five-column layout. Again, here, we won’t explicitly create rows via the grid-template-rows property but keep sizing the rows via the grid-auto-rows property.
  • To position and size the columns on the desktop layout and the ninth column on the mobile one, we’ll use the grid-row and grid-column properties.
  • We’ll use the object-fit: cover property value to place the images inside their column. This way the images will perfectly fit inside their container without losing their aspect ratio.

What is object-fit: cover?

That last point is really important. Without object-fit: cover our images will be forced to fit the dimensions of the grid cells, like this:

no object-fit exampleno object-fit exampleno object-fit example
Things look a little squished

But with object-fit we can define how the image is handled. With the cover value, each image will be cropped so that it retains its aspect ratio, whilst its smallest dimension (height or width) fits the container perfectly. It will cover the available space.

Perfect proportions with object-fit: coverPerfect proportions with object-fit: coverPerfect proportions with object-fit: cover
Perfect, cropped proportions

Final Styles

With that said, here are all the masonry layout styles:

1
.grid {  
2
  display: grid;
3
  grid-gap: 8px;
4
  grid-template-columns: repeat(2, 1fr);
5
  grid-auto-rows: 30vw;
6
  list-style: none;
7
}
8
9
.grid li:nth-child(9) {
10
  grid-column: 1 / -1;
11
  grid-row: span 2;
12
}
13
14
.grid figure,
15
.grid img {
16
  width: 100%;
17
  height: 100%;
18
}
19
20
.grid img {
21
  object-fit: cover;
22
  background: #f5f3f4;
23
  box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2);
24
}
25
26
@media (min-width: 850px) {
27
  .grid {
28
    grid-gap: 24px;
29
    grid-template-columns: repeat(5, 1fr);
30
    grid-auto-rows: 12vw;
31
  }
32
33
  .grid li:nth-child(1) {
34
    grid-column: 1;
35
    grid-row: 1 / span 2;
36
  }
37
38
  .grid li:nth-child(2) {
39
    grid-column: 2 / span 2;
40
    grid-row: 1 / span 2;
41
  }
42
43
  .grid li:nth-child(3) {
44
    grid-column: 4;
45
    grid-row: 1;
46
  }
47
48
  .grid li:nth-child(4) {
49
    grid-column: 5;
50
    grid-row: 1;
51
  }
52
53
  .grid li:nth-child(5) {
54
    grid-column: 4;
55
    grid-row: 2;
56
  }
57
58
  .grid li:nth-child(6) {
59
    grid-column: 5;
60
    grid-row: 2 / span 2;
61
  }
62
63
  .grid li:nth-child(7) {
64
    grid-column: 2;
65
    grid-row: 3;
66
  }
67
68
  .grid li:nth-child(8) {
69
    grid-column: 1;
70
    grid-row: 3;
71
  }
72
73
  .grid li:nth-child(9) {
74
    grid-column: 3 / span 2;
75
    grid-row: 3 / span 2;
76
  }
77
78
  .grid li:nth-child(10) {
79
    grid-column: 1 / span 2;
80
    grid-row: 4;
81
  }
82
83
  .grid li:nth-child(11) {
84
    grid-column: 5;
85
    grid-row: 4;
86
  }
87
}

This will give us the following result:

4. Dynamic Patterns

Great job so far, folks! We’ve managed to create an attractive masonry layout, filled with images. But we can go a bit further and automate things. The goal is to make this layout look great with more Unsplash photos (33) like this:

The new image gridThe new image gridThe new image gridWith this in mind, we’ll need to do three things:

  • Identify each item inside the image blocks (three blocks of 11) through an inline CSS variable (n). We’ll use this variable to place it in the right row. 
  • Use the :nth-child() CSS pseudo-class to create patterns that will dynamically select new items as they are added to the grid.
  • Automate the location of the items inside a grid row by grabbing their n CSS variable.

By putting all these in place, we’re leading to this fully dynamic grid:

Take some time to see what is going on here. Again, the best way to understand it is by using your browser tools to examine the placement of each item inside the grid!

Conclusion

Another exercise has come to an end, folks! Thanks for following along. Hopefully, you learned one or two new things about how to build creative image galleries with nothing but CSS.

You can extend this idea by using it not only for galleries but also for post lists and have a Load More Button for revealing different bunches of elements through AJAX, or perhaps combining this layout with infinite scrolling:

As always, thanks a lot for reading!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.