Pure CSS3 Masonry Layout

Just to explain this tutorial a bit more in detail, I'm writing it up. With CSS3, interesting layouts such as this one can be created with little to no frustration. Trust me when I say this, it takes 19 lines of CSS to accomplish the Masonry layout. That's it!

I will also be showing you how to break the flow of the Masonry layout with Flexbox clusters. This small, yet effective, addition will allow for a more interesting design of the data you are presenting. It is definitely worth looking into, but it is not necessary for this tutorial. Here are the pages I referenced while making this tutorial:

Time to move into the actual tutorial!


For those of you that had not watched the video, or cannot, I shall state that the finished product of this tutorial is ready for production-level projects. It has an incredibly smooth animation that does not hinder performance in the slightest, and it will not induce any migraines!

Dependency:
My HTML5 Setup:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta http-equiv="x-ua-compatible" content="ie=edge" />

        <title></title>

        <link rel="icon" href="data:;base64,iVBORw0KGgo=" />
    </head>

    <body></body>
</html>
Basic CSS:
<style type="text/css">
    *,
    *::before,
    *::after {
        -webkit-box-sizing:border-box;
        -moz-box-sizing:border-box;
        box-sizing:border-box;
    }

    html,
    body,
    body > header,
    body > section {
        height:100vh;

        position:relative;
    }

    * {
        margin:0;
        padding:0;
    }

    html { overflow:hidden; }
    body {
        overflow-x:hidden;
        overflow-y:auto;
    }
</style>

First, throw that into the head. Second, I use this CSS setup in nearly every one of my projects. Without this setup, I have found that html and body don't play nicely together in several situations, considering html likes to do its own thing with overflow.

Initial Testing Markup:
<article>
    <div class="inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
        proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
</article>
<article>
    <div class="inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
        proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
</article>
<article>
    <div class="inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation.</p>
    </div>
</article>

This is just a very basic markup to get a general idea of how the layout works. Add more articles to see how the effect works with a longer page length. hrow this into the body and look over the remaining CSS.

@supports (((-webkit-column-width: 17rem) or (-moz-column-width: 17rem) or (column-width: 17rem)) and ((-webkit-column-gap: 0.5rem) or (-moz-column-gap: 0.5rem) or (column-gap: 0.5rem))) {
    #masonry {
        -webkit-column-width:17rem;
        -moz-column-width:17rem;
        column-width:17rem;

        -webkit-column-gap:0.5rem;
        -moz-column-gap:0.5rem;
        column-gap:0.5rem;
    }
}

#masonry {
    width:100%;
}

#masonry > article {
    width:100%;

    display:inline-block; // without this, the columns will flow into the next
}

Told you, only 19 lines of CSS for the effect to work. It's pretty self explanatory, there are no set amount of columns, just sizes and spacing. Let's change a block and add a couple to make it a little more attractive:

#masonry {
    padding:1rem;

    width:100%;
}

#masonry > article p { margin:0.25rem 0; } // we're adding this

article p { // adding this one as well
    padding:0.25rem;

    background-color:#EEE;
}

With a little bit of spacing and a splash of color, our product looks a little nicer.

That is it for the Masonry layout actually! Quite easy, right? If you'd like to learn about the Flexbox clusters, keep reading!


Time for Flexbox Clusters

Cluster Markup:

Replace the above initial markup with the following:

<article> <!-- Flexbox Cluster: column -->
    <div class="inner">
        <div class="flex-cluster">
            <div class="flex-content half column">
                <p class="flex-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
                cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
                proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
            <div class="flex-content half column">
                <p class="flex-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                tempor incididunt ut labore et dolore magna aliqua.</p>
                <p class="flex-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                tempor incididunt ut labore et dolore magna aliqua.</p>
            </div>
        </div>
    </div>
</article>
<article>
    <div class="inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation.</p>
    </div>
</article>
<article> <!-- Flexbox Cluster: row -->
    <div class="inner">
        <div class="flex-cluster">
            <div class="row">
                <p class="flex-content">Lorem ipsum dolor sit amet.</p>
                <p class="flex-content">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
                cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
                proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
        </div>
    </div>
</article>

The flow of information can look a bit confusing, but it will make more sense when you look at the CSS:

/**
 * BONUS - Flexbox Clusters
 *
 * Any good masonry layout includes this to some degree. Why?
 * - To break the flow and have content stand out.
 *
 * Again, everything within this that is cosmetic will be marked as such.
 */
.flex-cluster,
.flex-cluster .flex-content {
    display:-webkit-flex;
    display:-moz-flex;
    display:-ms-flex;
    display:flex;
}

.flex-cluster .column {
    -webkit-flex-direction:column;
    -moz-flex-direction:column;
    flex-direction:column;
}
.flex-cluster .column p { margin-top:0 !important; }
.flex-cluster .column p:first-child { margin-top:0.25rem !important; }

.flex-cluster .row {
    -webkit-flex-direction:row;
    -moz-flex-direction:row;
    flex-direction:row;
}

.flex-cluster .flex-content { flex:1 1 auto; }
.flex-cluster .flex-content.half.column { flex:1 1 50%; }
.flex-cluster .flex-content.half.column:first-child { margin-right:0.25rem; }

Now you can play around with different combinations of the clusters and get really interesting flows going. Trying using this to your advantage!

This is all the necessary CSS to make the clusters work properly. Flexbox makes it incredibly easy to style a whole slew of elements without having to hack together uniform styles. Essentially, the clusters consume the entire space of their element, then give their largest child element priority, then split the remaining space evenly amongst the rest while trying to conform to the largest child's dimensions. I highly recommend reading the above mentioned articles to get a better understanding of Flexbox!

Conclusion:

To sum everything up, we basically mocked the style of any newspaper columns and provided our style twist. This can provide efficient information to your users while keeping your stylesheet fairly small. If it doesn't work, or you have some questions, just ask!