- 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.
01. Setting up Masonry
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.
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.
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.
margin: 0 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.
// other masonry options
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;
In your Masonry set-up, you’ll need to call up the following code.
// all other masonry options
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:
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.
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 .
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