Add Masonry layout for Shopify blog posts

I’m sure you’ve seen Masonry in action all over the web even if you weren’t aware of it. Masonry is a JavaScript grid layout library. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall. This site uses Masonry for its blog layout.

Anyway, I wanted to incorporate Masonry into my Hand and Hide website blog which is built on Shopify. I assumed there would be a Shopify app or at least a simple how-to to be readily found online, but I was wrong. There are lot’s of sites that talk about integrating Masonry into a generic website, but nothing specific for Shopify. I dove in and figured it out, but it took some time and effort, so I thought I’d share what I learned.

Let me preface this by saying that I am not a coder. I can generally manage to figure out what a section of code does and I can hack together various bits of code I find elsewhere, but coding from scratch is not a strength of mine. I know my way around HTML and CSS and now Liquid (Shopify’s language) fairly well, but JavaScript is another matter. This doesn’t stop me from working with it, but anytime I do, it involves lots of trial and error. I say all this just so you know that I am not an expert and that while what I did worked for me, it might not work for you and I might not be able to help you to get it to work for you either. As a precaution, make sure you have a backup of your theme in case something goes awry.

Also, my theme has a built in 3 column layout option which I am utilizing for the Masonry layout. If your theme doesn’t have an appropriate column layout, you’ll need to add that to your theme.

Anyway, here are the basic steps you’ll need to perform:

  1. Download the Masonry code
  2. Download the Images Loaded code (makes sure Masonry does its thing once the images are loaded and not before and thus avoids weird looking layout)
  3. Add both scripts to your Shopify assets folder
  4. Edit your theme.liquid header to call the scripts
  5. Add some JavaScript to initiate Masonry (also in the theme.liquid header)
  6. Add some JavaScript to your blog.liquid or blog.template.liquid
  7. Add some classes to 2 divs in your blog.liquid or blog.template.liquid
  8. Test it out
  9. Optionally tweak your theme’s CSS to fix any minor layout issues

If this all sounds reasonable, let’s get started…

Step 1 – Download Masonry code to your local drive (make note of where it is)

Step 2 – Download the Images Loaded code as well

Step 3 – Add both scripts to your Shopify assets folder. So we’ll be working in the Edit HTML/CSS section of your theme. To get there, go to Online Store from the admin sidebar and then click the three dots next to the blue Customize Theme button for your theme. Click Edit HTML/CSS and this should give you access to your theme files. On the left side click on the Assets folder (you may have to scroll down to find it) and then click Add new asset and then Choose File and navigate to where you saved the two scripts. Upload both scripts.

Step 4 (and 5) – Edit your theme.liquid header to call the scripts and add some additional JavaScript to initiate Masonry. Find your theme.liquid file under the Layout folder and click on it to edit it (if you have multiple layouts for your theme, you’ll need to figure out which one the blog page uses.) Place the following code

<!-- Masonry -->

{{ 'masonry.pkgd.min.js' | asset_url | script_tag }}
{{ 'imagesloaded.pkgd.min.js' | asset_url | script_tag }}
   
<script type="text/javascript">
    // init Masonry after all images have loaded
    var $grid = $('.mason').imagesLoaded( function() {
  	$grid.masonry({
            // Masonry options here
    	    itemSelector: '.article',
    	    fitWidth: true,
    	    columnWidth: '.article'
  	}); 
    });
</script>  

just above the

{{ content_for_header }}

in the header section of the file. Save the file.

Step 6 – Add some JavaScript to your blog.liquid or blog.template.liquid
Navigate to the Templates folder of your theme and click on blog.liquid
If it looks like mine

{% comment %}
  The contents of the blog.liquid template can be found in /sections/blog-template.liquid
{% endcomment %}
{% section 'blog-new' %}

then you’ll need to edit the blog.template.liquid (or whatever your theme calls it) in the Sections folder. Find and click on that file. Then add the following code at the very beginning of that file.

<script type="text/javascript">
        jQuery(document).ready( function( $ ) {
            
            /*
            * Handle Blog Masonry
            */
            function doMasonry() {

                var $grid = $( ".mason" ).imagesLoaded(function () {
                    $grid.masonry({
                        itemSelector: '.article',
                        columnWidth: '.article',
                        fitWidth: true,
                    });
                });
                              
            }

            /**
            * Call Masonry on window resize and load
            */
            $( window ).resize( function() {
                doMasonry();
            });
            doMasonry();
                        
        });

</script>

Step 7 Add some classes to 2 divs in your blog.liquid or blog.template.liquid. We’ll continue in the same file. You’ll need to locate the container div for the blogs and the individual blog divs in the file. Look for a loop like this:

{% for article in blog.articles %}

The word article may be another word, but blog.articles should be the same. You’ll need to find the container div just outside this loop.
Here’s what that part of my file looks like:

    <div class="mason {% if sidebar %}twelve{% else %}sixteen{% endif %} columns" >
      {% for article in blog.articles %}
        {% if section.settings.blog_articles_per_row == "1" %}
          {% if article.image %}
            <div class="{% if sidebar %}seven{% else %}nine{% endif %} columns alpha article_image">
              <a href="{{ article.url }}" title="{{ article.title | escape }}">
                <img src="{{ article.image | img_url: '1024x1024' }}" alt="{{ article.title | escape }}" />
              </a>
            </div>
            <div class="{% if sidebar %}five{% else %}seven{% endif %} columns omega article">
          {% else %}
            <div class="{% if sidebar %}eight{% else %}sixteen{% endif %} columns alpha omega article">
          {% endif %}
        {% else %}
            <div class="article one-third column">
        {% endif %}

   		<a href="{{ article.url }}" title="{{ article.title | escape }}">              
		{% if article.image %}
			<img src="{{ article.image | img_url: 'grande' }}" alt="{{ article.title | escape }}" />
	    {% else %}
			{% if article.content contains "<img " %}
   	 			{% assign src = article.content | split: 'src="' %}
   	 			{% assign src = src[1] | split: '"' | first | replace: '//cdn', 'http://cdn' | replace: 'http:http://', 'http://' | remove: 'https:' %}
     			<img src="{{ src }}" alt="{{ article.title | escape }}" />
    		{% endif %}    
		{% endif %}              
        </a></div></div></div></div>

In my case, the div right above the loop is the blog container div and I’ve added the class “mason” to that div as seen in the code. Next we’ll need to find the individual blog divs. In my code, there is some logic to determine the layout based on some theme settings and whether or not there is a sidebar. I determined that the divs with the class “article” were the individual blog divs (you can inspect your blog page using Chrome’s inspect tool (other browsers offer something similar) to help figure out what you need to look for.) In my case, I didn’t add a class to those divs, but just used the “article” class in the JavaScript that initializes Masonry. You can either add the class “article” to the appropriate divs or modify the code in steps 5 and 6 above to match what your theme already has. Save the file.

Step 8 – Test it out! If you did everything right, it should be up and running on your blog.

Step 9 – Tweak your theme’s CSS. Most likely, there will be some spacing issues that you’ll want to fix by editing your theme’s style.scss.liquid or your own supplemental css file. Here are the setings I used to add the rounded corners and shadow effect:

.article {
  border-radius:10px;
  background-color:#fff;
  box-shadow:2px 2px 9px #aaa;
}

.article img:first-of-type {
  border-radius:10px 10px 0 0;
}

If your blog divs have a different class you’ll need to change article to whatever that class is.

Leave a Reply