Building Highly Performant Masonry Layouts with Gatsby.js

Pulling in an additional dependency with its own styling approach⛔ Without client-side scripting, no image would show up by defaultWe were going to build a layout with a dynamic amount of columns based on pre-defined breakpoints:The mobile and desktop browsing experiences would vary based on viewport widthWhile it’s possible to pull off breakpoint-based layout transitions with regular media queries, using styled-components with Rebass felt more convenient and systematic.

Creating components with design systems in mindDefining the interface of a reusable React component is non-trivial, especially when it comes to responsiveness.

Media templates let developers declare breakpoints in an application-wide scope, but they can hardly be used for specifying responsive behavior through props.

????Fortunately, Rebass provides a way to address our issue by promoting the use of responsive props.

In addition, first-class support for design systems is realizable through themeable props.

????Defining the interface of a responsive masonry layoutIn order to control the amount of items per row with breakpoints, the desired API of our component became the following:The itemsPerRow prop allows us to show 2 images per row on smaller screens and 3 on larger displays.

Calculating the size of a single row itemOur gallery consists of rows in which the height of images are equal:Each row may have a different height, but the height of items in a single row is fixedImages should be sized in proportion to their aspect ratios.

For example, the second box shown on the figure above has an aspect ratio of y and should have a width of y / (x + y + z) relative to 100% (the row’s entire width).

The wider an image is, the more horizontal space it takes to reach the height of its (potentially narrower) neighbors.

As we are serving static images, the aspect ratio of them is known in build time.

Gatsby makes it possible to parse structured data from YAML files like the following:Querying metadata of the referenced images is also possible, through GraphQL.

As a bonus, we may also opt in to use gatsby-image for serving our images in the most appropriate sizes available:Loosening constraints to build the first prototypeAt first, we wanted to build a masonry component with multiple screen resolutions in mind.

Considering the complexity of our task, the first prototype should only be optimized for devices with smaller displays.

????The implementation is based on our calculations outlined earlier:Using Rebass is not necessary here, I used it only to make the code as similar to the next iteration as possibleOur component is already capable of rendering media acquired through GraphQL.

In the code below, the caption of each image is also constructed:As a result of server-side rendering, all the calculations are made upfront.

No JavaScript was executed on the client side to produce the layout below:We just crafted a page which works without JavaScript by using the power of JavaScript ????Making our gallery responsiveAt this point, the only challenge left to tackle is about handling different viewport sizes.

I annotated the code below, letting it speak for itself:Putting it all togetherCombining the code snippets above, a responsive masonry layout of any kind can be built, as long as the aspect ratio of each item is known in advance.

A real-world demo of the presented gallery can be found here, along with its source code published on GitHub.

This story is published in Noteworthy, where 10,000+ readers come every day to learn about the people & ideas shaping the products we love.

Follow our publication to see more product & design stories featured by the Journal team.


. More details

Leave a Reply