Pinterest's layout has always been the defining feature of the site since its inception. It has been used by many others since then, and I've always been fascinated by it. Recently, I've come to learn that this type of layout is called a Masonry Layout, a name that comes from the craft of stonemasonry. Another thing I've learnt recently is that CSS has an experimental masonry grid layout, with very limited browser support. The specifications are outlined in CSS Grid Layout Module Level 3 Editor's Draft for those who are interested.
(DALL.E's interpretation of a masonry layout)
Creating a Masonry Layout
There are a few different ways to achieve this layout. Horizontal masonry layouts are simpler to create than vertical ones1. You can simply use inline-block
elements, or use a flex
container with flex-wrap: wrap
if you want more control over the layout.
For a vertical layout, flex
doesn't do as well unless you have a fixed height container. An approach I like personally is to use columns2. Column layouts are responsive and allow setting the maximum number of columns. The following CSS creates a column layout with a maximum of 4 columns, each column having the ideal width of 180px
, and a gap of 10px
between columns3.
#column-layout {
columns: 4 180px;
column-gap: 10px;
}
The main issue with this approach is that the order of the child elements in the layout is vertical, not horizontal. The example below shows the above CSS in action. Note the order of the elements.
Approaches for a CSS Masonry Layout is a great read on the different ways a masonry layout can be achieved. It covers the cases above and more.
Enter Masonry CSS Grids
So far, CSS grid layout hasn't been flexible enough to create a masonry layout, but this might be about to change. The Editor's Draft introduces a new masonry
value to be used for grid-template-columns
and grid-template-rows
properties. The snippet below creates a responsive vertical masonry grid with columns having an ideal width of 180px
, and a gap of 10px
between the elements in the grid.
#masonry-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
grid-template-rows: masonry;
gap: 10px;
}
The result would look something like this:
(CSS Grid with grid-template-rows: masonry
)
If your browser supports masonry grids, you can see it in action here:
Examining the result, you'll notice that the order of the elements is horizontal, but they're not exactly in order. The masonry layout algorithm places elements in the columns with the most remaining space to try to achieve an even look for all columns4. If order is important, using masonry-auto-flow: next
will place the elements in order, but the final result won't be as even.
(Masonry Grid with masonry-auto-flow: next
)
Browser Support and Fallbacks
As of writing this, the masonry
value is only supported in Safari Technology Preview5 and in Firefox6 as an experimental feature. If any of the code samples above didn't look right, it might be because the browser you're using doesn't support it yet. If you really want to use it (I know I do), then make sure to provide a fallback for other browsers.
The default fallback when using masonry
in an unsupported browser, is to ignore it and use auto
instead. This example shows what the fallback would look like.
If that's not the look you're going for, you can detect support for the masonry
value using @supports
and provide alternative CSS for unsupported browsers. Here's how to fallback to the column layout we saw earlier.
#masonry-layout {
columns: 4 180px;
column-gap: 10px;
}
@supports (grid-template-rows: masonry) {
#masonry-layout {
columns: auto;
column-gap: 0;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
grid-template-rows: masonry;
gap: 10px;
}
}
For a live example, my personal website falls back to a hacky flex
layout if the browser doesn't support masonry grids.
-
Google Images layout is an example of a horizontal masonry layout, while Pinterest is an example of a vertical one. ↩
-
A multi-column CSS layout, flows an element's content into columns. ↩
-
The
column-gap
property only applies to the space between columns, not between rows (as the name might suggest). The space between rows can be set usingmargin
on the child elements. ↩ -
The algorithm is explained in more detail in the editor's draft ↩
-
Enabled since version 163. See the release notes ↩
-
Available since version 77 and enabled by default in Nightly. Can be enabled from
about:config
by settinglayout.css.grid-template-masonry-value.enabled
totrue
. See the release notes ↩
Top comments (10)
Never understood why anyone thought this layout was a good idea. Really difficult to scan with your eyes
I think this in the vein of "sometimes we just want something which isn't really functional, but which looks cool" ;-)
Absolutely. Also why does this sound like the motivation behind every side project I work on :D
I find it quite visually appealing, but you make a very good point. I'd think the amount and type of data presented need to be considered when choosing such a layout.
Do you think a horizontal masonry layout (e.g. Google Images) is easier to scan or is the same?
Horizontal works much better
Because some people want to see more cards at once and pick something they're interested in
This one can be made easily with flexbox or not ?
I will try it
It can if you don't mind vertical ordering of the items and I think you'd need a fixed height layout, but that's only if you're making a vertical (Pinterest style) layout. Let me know if you end up trying it!
I think too. I will tell you after
cool