For those that don't know, Masonry is a JavaScript grid layout library. It lays out your page in such a way that "bricks" of content are all carefully positioned so they form what appears to be a wall of brilliance, making all those who visit your site gasp in wonderment.

This style of design is massively popular, you will find it all over the Internet - and if you haven't noticed it before, now you know about it you will see it being used all over the shop. One high profile site using such a layout is Pinterest:

So what's so great about it anyway?

Masonry uses some very clever calculations to work out the height of all the elements you'd like to "masonryfy", and then positions them on the page such that there is no excess space between them. This type of layout is impossible to replicate by using css alone. Let's see an example:

    

<div class="masonry-block">
    <img src="/images/rings-s.jpg"/>
    <img src="/images/ribbon-s.jpg"/>
    <img src="/images/flowers-s.jpg"/>
    <img src="/images/groom-s.jpg"/>
    <img src="/images/kiss-s.jpg"/>
    <img src="/images/car-s.jpg"/>
    <img src="/images/confetti-s.jpg"/>
</div>

    

.masonry-block img{
    float: left;
    width: 50%;
}

These images have been given a width of 50%, and floated left. But look what's happened, because the ribbon image is portrait orientation, when it floats to the left and hits the edge of the first image (of the hand), it leaves a huge white gap that no other image following it can fill.

And look at the image of the flowers, and the image of the groom having his flower adjusted. The height of the flowers image is just a couple of pixels bigger than the groom - but that tiny amount is enough for the portrait image of the couple kissing to float up alongside it too. Another unavoidable huge white gap!

You could get around this by avoiding portrait images completely, and then making sure every single one of your landscape images exactly the same dimensions. The images would then float perfectly next to each other and form a grid because they're all the same height. But then you're compromising... and who wants to do that when an extra cool alternative is available?!

Masonry - The Solution

Add the following into your HTML code. This loads the Masonry library, which allows you to use the new layout. Note - the "Images Loaded" file is not strictly necessary but it's a good idea to use it. Basically it makes sure that before Masonry creates your wall, all of your images have been fully loaded. By doing so, it makes sure your "bricks" all have the correct dimensions:

    

<script src="https://npmcdn.com/imagesloaded@4.1/imagesloaded.pkgd.min.js"></script>
<script src="https://npmcdn.com/masonry-layout@4.0/dist/masonry.pkgd.min.js"></script>

Add a class of "grid-item" to each one of your images, and an empty div "grid-sizer". This markup is what we'll use to identify which elements we want to be part of our wall, and also what size they need to be.

    

<div class="masonry-block">
    <div class="grid-sizer"></div>
    <img class="grid-item" src="/images/rings-s.jpg"/>
    <img class="grid-item" src="/images/ribbon-s.jpg"/>
    <img class="grid-item" src="/images/flowers-s.jpg"/>
    <img class="grid-item" src="/images/groom-s.jpg"/>
    <img class="grid-item" src="/images/kiss-s.jpg"/>
    <img class="grid-item" src="/images/car-s.jpg"/>
    <img class="grid-item" src="/images/confetti-s.jpg"/>
</div>

Add the following into your CSS file, which will let Masonry know what percentage each column should be. In our case it's 50%, because we have two columns of images we're trying to work with:

    

.grid-item,
.grid-sizer{
    width: 50%;
}

And finally add the following into your JavaScript (jQuery) file, to get Masonry going:

    

var $grid = $('.masonry-block').imagesLoaded( function() {
    // initialise Masonry after all images have loaded
    $grid.masonry({
        itemSelector: '.grid-item',
        columnWidth: '.grid-sizer',
        percentPosition: true
    });
});

Now if you refresh your page, you should get something like this!

Masonry has calculated the dimensions for every single one of your images (grid-items), and arranged them on the page to show the least amount of ugly white space. I don't know about you, but personally I think that looks a hell of a lot better. As with most things, you can stop there or you can get way more involved and in depth. Visit the Masonry website and check out the options and methods to find out more. I'll just go through one possible addition as an example.

Adding a Gutter

Ironically, after just removing a huge load of white space from our gallery, I'm actually thinking we need to add some back in. To me the images look too close together, it feels like we need to give them some breathing room. We can use the "Gutter" option Masonry provides to help with this.

Add an empty "gutter-sizer" div right underneath our grid-sizer div, like so:

    

<div class="masonry-block">
    <div class="grid-sizer"></div>
    <div class="gutter-sizer"></div>
    <img class="grid-item" src="/images/rings-s.jpg"/>
    <img class="grid-item" src="/images/ribbon-s.jpg"/>
    <img class="grid-item" src="/images/flowers-s.jpg"/>
    <img class="grid-item" src="/images/groom-s.jpg"/>
    <img class="grid-item" src="/images/kiss-s.jpg"/>
    <img class="grid-item" src="/images/car-s.jpg"/>
    <img class="grid-item" src="/images/confetti-s.jpg"/>
</div>

Change our CSS rules slightly to make our columns slightly thinner, then specify the width of our gutter. In our case the total should add up to 100% because we want our gallery to fill the whole width of the screen (48 + 48 +4 = 100). Also add some margin bottom to each image:

    

.grid-item,
.grid-sizer{
    width: 48%;
}

.gutter-sizer{
    width: 4%;
}

.grid-item{
    margin-bottom: 4%;
}


Slightly change our jQuery code that runs Masonry, to take into account our new gutter-sizer div:

    

var $grid = $('.masonry-block').imagesLoaded( function() {
    // initialise Masonry after all images have loaded
    $grid.masonry({
        itemSelector: '.grid-item',
        columnWidth: '.grid-sizer',
        gutter: '.gutter-sizer',
        percentPosition: true
    });
});

And now we have our extra spacing:

Opinion will obviously vary, but to me that looks a lot better than it did previously. Each image stands out far more when it has that extra bit of room.

So there you have it, go forth and Masonry! Remember, you don't have to only use images. Why not get more creative and add some text with them too? Have a look at Pinterest as an example. The great thing about Masonry, is each separate brick can have as much or as little text as you like. It will still calculate the overall dimensions, and make sure your layout looks perfect!

As usual, if you need any help let me know in the comments.