Get started with jQuery Masonry

  • Knowledge needed: Basic HTML, CSS, and JavaScript / jQuery
  • Requires: Text editor, modern browser
  • Project Time: 1 hour
  • Support file 1

This article first appeared in issue 229 of .net magazine.

The explosion of Pinterest has seen its design and user experience praised. But unless you’ve been living in a cave for the past two years, you’ve probably seen a similar concept on many smaller sites, such as portfolio sites and Tumblr accounts. This is made possible via Masonry, a dynamic grid layout plug-in for jQuery – Pinterest has created custom script for this, but the concept is identical to Masonry’s. David DeSandro, Masonry’s creator, describes it as “the flip-side of CSS floats”. In traditional CSS floats, objects are arranged horizontally then vertically. Masonry reverses this, and can optimise the available space in a grid.

With the recent explosion of attention on Pinterest, there has been an increased emphasis on Masonry

With the recent explosion of attention on Pinterest, there has been an increased emphasis on Masonry

Masonry measures all of the items you’re serving and rearranges them in the best way with what is spatially available. This solution works especially well with image-based content, facilitating a virtually seamless wall of pictures pieced together. Without Masonry, a design like this would be virtually impossible, but the plug-in makes it attainable in just a few lines of JavaScript.

01. Setting up Masonry

Before you begin you’ll need basic HTML, CSS, and JavaScript set up. I’ve included a simplified version of this from HTML5 Boilerplate. In the demo.html file, I’ve added 10 different elements I want to be laid out by Masonry. Each of these elements has a class of item and simply contains an image. Our style.css file declares the basic styles for these items, making them 300px wide, display block, float left and have a top and right margin of 20px.

Let’s look at what this looks like before Masonry is applied. In your demo files, comment out script.js at the bottom of the demo.html file for the ‘un-Masoned’ layout. You’ll notice inconsistent vertical spacing between images: taller images in a row will create a gap below the other elements, making your layout sloppy. Unless you’ve a specific cropped size for all elements or static content that you control, a solution displaying a range of content in a uniform manner can be tricky. Masonry shines here, optimising your dynamic content’s layout on the fly.

We’re ready to apply Masonry, so uncomment script.js. Create a $(document). ready() function and call the Masonry function on our content container.

$(document).ready(function() {
$('#content').masonry({
columnWidth: 320,
itemSelector: '.item'
}).imagesLoaded(function() {
$('#content').masonry('reload');
});
});

Masonry has several options available, but these are the two essential ones. columnWidth specifies the minimum width for each column. This takes padding and margins into consideration, so 320 is for a 300 pixel width image plus 20 pixels of right margin. itemSelector specifies the CSS selector for all items that will be affected by Masonry. We’re also calling on a plug-in shipped with Masonry called imagesLoaded that tells Masonry to reload – but we’ll get to that later.

Now let’s look at the output; it’s critical to understand how this is achieved. We can see now that our Masonry container, #content, has been given a class of .masonry and is given a relative position and hardcoded height in pixels. What this does is enable each element, or brick, to be positioned absolutely with an exact top and left measurement based on the width and height of the brick.

02. Issues with images

One of the most common issues with Masonry is elements, especially images, overlapping each other. Masonry works by measuring every available brick, and fits each one together based on those measurements. The issue is that when Masonry measures the elements, the images may not be loaded in – so Masonry will measure the brick without the image dimensions. This means instead of having the full height (or width) of the image, it will only occupy a single line.

There are various ways to overcome this; each has pros and cons. The most common solution is to wait until all images are loaded by the browser and then initialise Masonry. You can accomplish this by using $(window).load() instead of $(document).ready() to begin your code. While this gives the desired output for Masonry, you make the user wait to be presented with the layout. It will also show a brief moment of your layout without Masonry before snapping into place. Finally, this solution distances your Masonry code from the rest of your JavaScript, which segregates your logic and can get messy if other parts of your code rely on Masonry being initiated first (such as Infinite Scroll).

If your assets haven’t been preloaded, there’s no way for Masonry to measure their size to place them properly

If your assets haven’t been preloaded, there’s no way for Masonry to measure their size to place them properly

A more robust solution is writing out the width and height of each image element in your markup. By having these values in the markup, Masonry will measure them correctly and not need to wait until the image is loaded to determine its size. The one major con to this is that it requires you have each dimension available and stored in your database, which is not always possible.

As this issue is widespread, Masonry ships with imagesLoaded, a plug-in that, yes, tells you when your images are loaded. imagesLoaded has a callback function that executes once all images are loaded in, which is the ideal place to initialise Masonry. I consider the most versatile option to be calling Masonry on document.ready and remeasuring once images are loaded. To do this, you’ll need to use Masonry’s reload method. I prefer this, because it enables you to keep your logic in one place, and forces the re-measure once images are ready.

03. Ideas for advanced users

Congratulations, you’ve got your Masonry layout set up – but this only scratches the surface of what Masonry can do. Once you’ve set up your initial Masonry instance, you can modify it using the plug-in’s methods. These are additional functions built into Masonry to help it do exactly what you want it to, such as adding and deleting items, re-measuring brick sizes and much more. You also have options for animating content, adding in new bricks – even RTL support. For our example, let’s create an animated flexible width. Change the width of #content to auto and a margin-left and margin-right of auto in style.css.

#content {
margin: 0 auto;
width: auto;
}

We also need to set isFitWidth to true to our Masonry set-up in script.js. isFitWidth is an option in Masonry to determine the largest column count possible for the browser’s current width. This is very useful for centring content without awkward gaps; without it Masonry will hold on to the leftover space that isn’t quite as wide as a column, meaning your container is never truly centred.

$('#content').masonry({
// other masonry options
isFitWidth: true
});

In the browser, hit Refresh: you can now resize your browser and the Masonry container will recalculate its width to match how many columns it can show.

Masonry can also animate these bricks as they go into their new positions, thanks to logic that puts a left and top CSS value on each brick. There are various ways to achieve this, some better than others. The most obvious is to use jQuery, which you can turn on by calling isAnimated: true when calling on Masonry.

This does the job, but jQuery animation relies on DOM manipulation and having several large bricks can slow down the animation performance and make the experience feel sluggish. Another way to accomplish it is by using CSS transitions, which will animate the left and top CSS properties. Going into all the benefits of using CSS transitions over jQuery animations is an entirely separate discussion, but using CSS to do your animations is much more robust and will perform better under almost every circumstance with Masonry. To use CSS transitions, put these values on .item in style.css, letting left transition to its new value, followed by top once left has done animating.

-webkit-transition: left .4s ease-in-out, top .4s ease-in-out .4s;
-moz-transition: left .4s ease-in-out, top .4s ease-in-out .4s;
-ms-transition: left .4s ease-in-out, top .4s ease-in-out .4s;
-o-transition: left .4s ease-in-out, top .4s ease-in-out .4s;
transition: left .4s ease-in-out, top .4s ease-in-out .4s;

While support for CSS transitions has rocketed over the past year, they’re not supported by older browsers that may make up a big part of your audience. If you want to use CSS transitions without sacrificing animation for some users, there’s a way to use both animation techniques for optimal performance, depending on browser capabilities. This uses a JavaScript library called Modernizr, which detects whether a user’s browser has features such as CSS transitions available via Modernizr.csstransitions, which is set to true or false depending on the user’s support for CSS transitions.

In your Masonry set-up, you’ll need to call up the following code.

$('#content').masonry({
// all other masonry options
isAnimated: !Modernizr.csstransitions
});

This is the ideal way to perform animation, because you’re serving the best possible experience to the user. Users who can take advantage of CSS transitions are able to, and those who aren’t are still given animation via jQuery.

04. Issues with enterprise use

Masonry has a large amount of use in Tumblr and smaller websites, and is easy enough to initialise. But setting it up for enterprise use is an entirely different ball game, with its own issues outside of images overlapping. Until now, we’ve always known how many items are going in our Masoned layout, and never minded where any of the elements were placed as long as there was no overlap.

The key to almost all issues with Masonry is reloading, so you can measure your new items and fit them into your layout. Sometimes this is much easier said than done, especially when loading in iframes, embedded content or content from a third-party script. You can extend Masonry to measure these elements as you need to and then call on Masonry’s reload method like so:

$('#content').masonry('reload');

Masonry will optimise the positioning of each brick by default, but sometimes you need a piece of content to be consistent in where it’s placed. If this applies to you, Masonry has a featured called cornerStamp enabling you to always have a brick in a certain spot. This works via the plug-in saving space for this brick when calculating its layout, which is helpful for advertising slots or promotional material. Find more info on cornerStamp here.

05. Debugging Masonry

If you’re still having issues there are resources out there: use your console and see what’s going on. From the console you can update options, issue methods, check widths and heights, and more. So if one or more bricks are not being measured correctly, you can edit your CSS from the browser tools and reload Masonry to see if your changes were successful. The data from each Masonry instance is available too. You can edit options on the fly and see if your Masoned object was initialised correctly. To view this, type the following into your console.

$('#content').data('masonry');

Another great idea for anyone using Masonry is to look at the source code on GitHub – it’s maintained by DeSandro himself. If you’re wondering how measuring happens, you can find the function that does this in layout() and _placeBrick(). It’s important to have an idea of what the plugin is doing internally, especially if this is key to your site’s presentation.

If you’re truly stumped, you can always turn to the Issues section on GitHub. When posting an issue, try to be as descriptive as possible and include a link to where the problem is occuring. Being able to see what’s going wrong makes debugging infinitely easier and will save everyone involved considerable amounts of time. DeSandro has posted guidelines for submitting an issue on his Github account, which you can view here .

06. Conclusion

Hopefully this article has shown you a few of Masonry’s capabilities – though I’ve only covered the beginnings of what’s possible and new use cases are constantly being developed. You can extend Masonry with functionality such as Infinite Scroll, multiple instances and more to maximise the user experience. Masonry is a great plug-in that has changed how people are designing for and interacting with the web. It’ll only get better as more people participate and contribute.

Thanks to Jacob Van Loon for the images used in this tutorial

Luke Shumard works as a senior web designer for Dazed Digital and AnOther, two of the largest independent fashion and lifestyle publications in the UK.

Thank you for reading 5 articles this month* Join now for unlimited access

Enjoy your first month for just £1 / $1 / €1

*Read 5 free articles per month without a subscription

Join now for unlimited access

Try first month for just £1 / $1 / €1

The Creative Bloq team is made up of a group of design fans, and has changed and evolved since Creative Bloq began back in 2012. The current website team consists of eight full-time members of staff: Editor Georgia Coggan, Deputy Editor Rosie Hilder, Ecommerce Editor Beren Neale, Senior News Editor Daniel Piper, Editor, Digital Art and 3D Ian Dean, Tech Reviews Editor Erlingur Einarsson and Ecommerce Writer Beth Nicholls and Staff Writer Natalie Fear, as well as a roster of freelancers from around the world. The 3D World and ImagineFX magazine teams also pitch in, ensuring that content from 3D World and ImagineFX is represented on Creative Bloq.