Showing Multiple Variant Images with Shopify Metafields


Unfortunately, Shopify product pages only allow one variant image. It isn’t a great experience because the variant images are grouped together with all the combined variant and product photos, jumbled into one big heap. Today we are going to change this behavior and add variant images using custom metafields. Now we can show only our set of variant images on each given variant option. Let’s get started.

Github code: https://github.com/ndrishinski/blogs/pull/1/commits/0298f131e3998b9b9d688cc29f5257c4e85993a9

Prefer video?

Enjoy, otherwise read on!

Create Variant Image Metafields

The first thing we want to do, is enable metafields on our variants so that we can select some images to use. First navigate in the Shopify dashboard to Settings -> Custom Data -> Variants and click ‘Add Definition’.

I’m using different colors as my variants, so I’ll first add one called ‘Variant Color’ and select ‘One value’ as a type of ‘Color’.

Then I’ll click ‘Add Definnition’ again and name this one ‘Variant Images’. I will give it a type of ‘File’ and choose ‘List of Files’.

Add Variant Images

Now that we have created our variant metafields, let’s navigate to the product and add our different images. In the dashboard navigate to Products -> (desired product). We are going to click into each variant and add the desired color and images to the bottom metafields that we created like so:

Add Custom Code

Now I am working in the Dawn theme, however you can take this logic and appy it to whichever theme you may be using in the default product page. The first thing we are going to do, is make the variant option buttons show the variant color. To do this navigate to product-variant-options.liquid and swap out the buttons for this:

<label 
    data-variant-id="{{ product.variants[forloop.index0].id }}"
    class="metafield-variant-options"
    for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" style="background: {{ product.variants[forloop.index0].metafields.custom.variant_color.value }}">
      {{ value }}

Check out the full file here. We are now adding the background color which we defined in the metafields above.

Next navigate to product-media-gallery.liquid file. All the code changes are too large to put here so check out this link to see the code diffs. The main portions I’ll highlight are:

{% for variant in product.variants %}
  {% for image in variant.metafields.custom.variant_images.value %}
     ...
     <img src="{{ image | image_url }}"
              data-variant-id="{{ variant.id }}"
              style="{%  unless product.selected_or_first_available_variant.id == variant.id %}display:none;{% endunless %} width: 40vw;"
            >

Instead of looping through the default product images, we are looping through the variant metafield images that we have added.

We also add this block of JavaScript:

<script>
      window.selectedVariant = {{ product.selected_or_first_available_variant.id }}
      document.addEventListener('DOMContentLoaded', function() {
        function swapImages() {
          window.selectedVariant = this.dataset.variantId
            document.querySelectorAll('.product__media-list li img').forEach(i => {
                if (i.dataset.variantId == window.selectedVariant) {
                    i.style.display = 'block'
                } else {
                    i.style.display = 'none'
                }
            });
        }
        document.querySelectorAll('.metafield-variant-options').forEach(i => {
            i.addEventListener('click', swapImages);
        });
    });
    </script>

This code is listening for the variant buttons to be clicked, and then swaps out the matching variant images. This ensures we are always dynamically rendering the correct variant images.

There are two more small code changes to make in various files that you can see here. But these are the main changes.

Conclusion

After saving these file changes and navigating to our product page, we should see a dynamic product page that renders matching variant images based on the selection! I hope you enjoyed this tutorial and please let me know what you think!