DEV Community


Posted on

Build a Masonry layout (Pinterest layout)

Recently, I worked on a side project that allows people to pin videos by link or upload images and I want to display them in the pinterest-style layout. After some research, I have figured out some effective methods to build that layout, including the use of some JS libraries. But for simplicity, I took the only CSS ways.

1. CSS columns approach

This approach will leverage the CSS columns with column-count CSS property that breaks an element's content into the specified number of columns.

.board-grid {
  column-count: 4;
  column-gap: 1em;
Enter fullscreen mode Exit fullscreen mode

The CSS rules above will style the board into a three column layout without a defined vertical axis.

If you have images with captions, then you want to avoid the stiuation where a the image and caption split across columns, you should use the page-break- properties:

.item {
    -webkit-column-break-inside: avoid;
    break-inside: avoid;
    page-break-inside: avoid;
Enter fullscreen mode Exit fullscreen mode

It is even easier to build a responsive layout with Tailwind CSS, just use columns-{count} with breakpoint. For example, md:columns-3 will apply the columns-3 at only medium screen sizes and above.

<div class="columns-2 md:columns-3 lg:columns-4 gap-6">
  <div class="break-inside-avoid"></div>
Enter fullscreen mode Exit fullscreen mode

The demo I built by Tailwind CSS, but idea is the same with pure CSS:

The only drawback of this approach is that the ordering of the masonry tiles are vertical — from top to bottom — rather than being shown horizontally from left to right.

2. CSS grid approach

The hard part of this approach is that CSS Grid creates two dimensional grids with strict rows and columns, whereas masonry is about letting elements fit themselves into space horizontally and vertically.
A 2 dimensional grid

The trick is using grid-auto-rows property to sets the unit height for our masonry. Then adjusts each block's height to match the grid with a little bit of math to calculate how many rows they should span.
With H as the height of the block, if we set grid-auto-rows value to R, grid-row-gap value to G, an appropriate span number (S) for any given block can be calculated by:

S = H / (G + R)
Enter fullscreen mode Exit fullscreen mode

For example:

.board-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 300px);
  grid-auto-rows: 20px;
  grid-gap: 10px;
Enter fullscreen mode Exit fullscreen mode

The value of grid-auto-rows is 20px, and value of grid-gap is 10px; so if the height of the element is 300px, it will span 10 rows.

  grid-row-end: span 10;
Enter fullscreen mode Exit fullscreen mode

The ideas of this approach I borrowed from

View details on demo:

View more about a side project I working on. It is called Mood Opus - a simple mood board that allows people to pin videos by link or upload images and display them in the Masonry layout.

Top comments (1)

schemetastic profile image
Rodrigo Isaias Calix

Really cool! I didn't know about the second approach, I hope to implement it in a future project.