tetchi blog

Tetchi's blog about life and stuff

Shopify Tutorial: Associating Product Variants with Product Images


UPDATE 11/10/2012: There is now an official, non-hacky solution for associating variants and product images! Check out the Variant Images app by the awesome Blake Mesdag and Mark Dunkley :)

In this tutorial I’ll be showing you how to associate product variants with product images using jQuery and Shopify’s new feature for adding unique alt tags for product images. For demonstration purposes I’m going to be modifying one of Shopify’s free themes, Radiance, but this technique will work with any theme. You can check out demos of this in action here (single option) and here (multiple options).

The screenshot below shows what the Radiance’s theme looks like initially. The first thing we’re going to do is set up the product’s variants and alt tags. After that, we hide the #thumbs <ul>. Finally, we’re going to add some Javascript to make it so that the options dropdown in the top-right corner changes the image inside the #active-wrapper div with the appropriate product image. For example, if you select “Black” for colour, #active-wrapper will show the product image with the black shirt.

Radiance theme’s default product page.

Sounds easy, right? Let’s get started!

1. Set up your product variants and product image alt tags.

The first thing you must do is match up your product’s variants with your product image’s alt tags. In order for this to work, the product’s variants must be exactly the same as the product image’s alt tags. The screenshot below shows you an example of a proper setup.

It’s important to note that you can only make a product association with one option. You can certainly have up to three options for your product (for example, I added a “Size” option here), but only one will affect what product image is shown. In step 3, you’ll see how to choose which option is tied to the product images.

variants and product image alt tags

An example of a proper variants and alt tag setup.

2. Hide the thumbnails (optional)

The next step is to hide the thumbnails with CSS. This step is optional, but to me it makes sense to hide them because the variant-selecting dropdown should be the only thing that controls what’s shown as the main image.

To do this in the Radiance theme, I simply added the existing “hidden” class to the <ul> that contains all of the thumbnails, as shown below. It’s important to still output the images (although they won’t be visible) because 1) we can pre-load the images and 2) we need to grab the ‘src’ attribute of the images when we swap the main image inside #active-wrapper.

I’m also going to change the product_img_url value inside the <img&rt; tag from ‘thumb’ to original, so that we load the biggest possible product image inside #active-wrapper. In reality you can strip out a lot more of the code below, but for the purpose of this tutorial I’m just going to keep it as is.




Your product page should now look like this:

No thumbnails!

2. Look for the selectCallback function

If you’re using a theme from the Shopify Theme Store, the chances are high that it is using the OptionSelector javascript. This means that the theme contains a function called selectCallback.

The selectCallback function is called whenever a user selects a different option through the options dropdown menu, and it’s used to update the variant’s price and Compare At price. Since the image-swapping needs to happen when the user selects a different option, why not place our JS in selectCallback? :D

What you can do is place the code in the Step 3 inside the selectCallback function, which is usually located in “product.liquid” or “theme.liquid”. In Radiance, it is located at the bottom of “theme.liquid”.

What if your theme does not use OptionSelector? Worry not, there are other solutions. Your theme may be using a dropdown menu or radio buttons for single-option products. In that case, you can use jQuery’s change() method instead to trigger the Javascript code in Step 3.

3. Add some code to selectCallback

Paste the code marked in blue. The first bit of Liquid goes outside of the selectCallback function. Everything below “//Swapping images JS” goes inside the selectCallback function.



{% assign option_to_match = 'Your Option Name Here' %}
{% assign option_index = 0 %}
{% for option in product.options %}
  {% if option == option_to_match %}
    {% assign option_index = forloop.index0 %}
  {% endif %}
{% endfor %}


 

First, what we need to do is set what option we want to associate with product images. This is done by changing the value of the 'option_to_match' variable, marked in red in the above code snippets. In this tutorial's example, options_to_match would be "Color", because that's the name of the option for our variants. The Liquid code does a forloop to save the index number of the chosen option which is then used in the following Javascript snippet. Big thanks to Caro for this Liquid snippet, as without it this technique would only work for single-option products.

What the Javascript code does is it saves the variant title of the selected variant in the dropdown inside a variable, and then looks for the product image inside #thumbs that has the same alt tag as the value of the variable. Once it finds the matching product image, it takes the value of the src attribute of the matching image and places it inside the src value of the image that's currently inside #active-wrapper.

Conclusion

That's all there is to it! If you're having trouble, make sure that you have set up the product alt tags and variant titles correctly, as outlined in Step 1. Please leave a comment if you have any questions or feedback!

UPDATE: I received some feedback from my peers, and it really makes no sense to limit this to one option. For example, for shirts it makes sense to have the colour and another option for size. I will be updating this article tonight to address this.

UPDATE 2: The code now supports multiple options thanks to the help of the incredible Caroline Schnapp!

UPDATE 3:Made some big fixes - sorry for the confusion guys. Also fixed a silly variable naming mistake. Thanks Czarto for catching that!

53 Comments

  • Rick
    Rick on January 25th, 2012

    Nice! What if each color has multiple images (e.g. back and front)?!

  • tetchi
    tetchi on January 25th, 2012

    Hmm, the way it’s set up in this tutorial, you can only have one image per variant. This tutorial’s really meant to be a simple ‘base’ for variant/product-image association, so I hope someone awesome comes up with a solution for multiple images per variant :). You could potentially set it up so that the Javascript checks for which product images’ alt tags include the variant title (instead of looking for an exact match, as it is now) and then show those images!

  • Dave
    Dave on January 26th, 2012

    Interesting approach. I guess the only thing that would keep me from using it is the fact that the alt tag of an image is meant to describe the image. In this case, Orange as the variant title and Orange as an alt tag is benign, but it will rarely be so easy with 2, 3, or more word variant titles.

    It would be awesome for the technique if the Admin would offer the ability to inject a data- attribute with whatever code you wanted, like a variants SKU for example. You could then use the same Javascript pattern, and not hurt the image search SEO.

    Any, it is progress and for n00bs with simple variants, will do just fine! Thanks for the example and for pointing out the image alt feature.

  • tetchi
    tetchi on January 27th, 2012

    Hey Dave, I definitely agree with you there. I think what might be better is if I check to see if the alt tag title includes the variant title. That way, you could have the something more meaningful, like “Orange tee shirt” as the alt tag, and check to see if the variant title “Orange” is in it.

    I’ll see if I can get around to that when I get a chance! Thanks for the feedback :)

  • thelovedone
    thelovedone on January 29th, 2012

    Hi tetchi

    I’ve been trying to incorporate this into my site but with no success. I’m not using the Radiance theme (using the Couture theme as a base), but I tried to rework the div calls in the script to match mine. The theme does use the selectCallback function, but I still couldn’t figure out exactly where to put each snippet of code. I’ve tried it a dozen different ways, and it’s hard to tell at what point it’s not working since it doesn’t break anything. If you have time to help me out I’d really appreciate it, this is a great feature that I’d love to incorporate.

    Thanks!

  • tetchi
    tetchi on January 29th, 2012

    Hmm, it’s really hard to say without seeing your shop. What’s the URL of your shop?

    EDIT: Oops, I see that your URL is there, but since it’s password-protected I won’t be able to tell what’s wrong.

  • Brian
    Brian on February 2nd, 2012

    Hi Tetchi

    I too have couture as a base and can’t seem to get it to work. I’m certain it’s something I’m doing wrong.

    I don’t see the exact callback code above your blue code in my product.liquid (other callbacks are there however), so I’m not sure exactly where to paste it. Also, I’m unsure what the appropriate name of the image id should based on this theme which uses cloudzoom.

    I have a password on my store which is: “temp”

    And here is a link to a test product with variants and alt tags all ready to go: http://goo.gl/74Xfz

    I hope you can help.
    Thanks,
    Brian

  • Czarto
    Czarto on February 3rd, 2012

    I believe you have one line of javascript extra highlighted that shouldn’t be:

    var selectCallback = function(variant, selector) {

    Maybe I’m missing something, but I had to exclude this line of code as it already existed in my .liquid

  • Czarto
    Czarto on February 3rd, 2012

    This is great stuff!

    I think in this line of the selectCallback js:
    $(‘#active-wrapper img’).attr(‘src’,imageName);

    imageName should actually be imageSrc like so:
    $(‘#active-wrapper img’).attr(‘src’,imageSrc);

  • Czarto
    Czarto on February 3rd, 2012

    This is the final javascript I ended up using. Some notes:

    1. You will notice that I added a condition. If no match is found on the ALT text of them thumbnails, then it will attempt to wildcard match on the filename.
    2. I am using _small images for my thumbnails, and so during the replace I swap them to the _grande version
    3. I am grabing only the first word from my variant tile, as in my store, my variant comes out as “Black Ladies 5”, whereas I only want the color.

    if( variant && variant.title ) {
    var colourName = variant.title.replace(/^(\w+)(.*)/, ‘$1’);
    var imageSrc = $(“#thumbs img[alt='”+colourName+”‘]”).attr(‘src’);
    if( !imageSrc ) { // Try to match based on image src filename
    imageSrc = $(“#thumbs img[src*='”+colourName.toLowerCase()+”‘]”).attr(‘src’);
    }
    if (imageSrc) {
    $(‘#featured img’).attr(‘src’,imageSrc.replace(‘_small’, ‘_grande’));
    }
    }

    Hope this is helpful to someone.

  • mkengi
    mkengi on February 7th, 2012

    Hi tetchi

    This is exactly what need, but i can’t get it to work. I have tried this in many different ways. I am missing something totally, but i cant figure it out. Even if i use Radiance theme to match yours (just for test). Any pointers or noob mistakes that i might be doing?

    Thanks

  • Yasuko
    Yasuko on February 9th, 2012

    Hi Tetchi,
    Thank you very much for this post.

    Like, thelovedone above, I’ve been trying to incorporate this into my site, but with no success. I’m using the Couture theme. I am confusing at step 3. This may be too stupid to ask, but I don’t know witch file to add those codes you mentions on step 3. In other words, where I can find “selectCallback” function…?

    If you could help me out, I would really appreciate it !!!

    Thank you!

  • tetchi
    tetchi on February 9th, 2012

    ^ Hey guys, sorry I made some silly mistakes.

    1) As Czarto pointed out, I messed up on of the variable names.
    2) I forgot to include a really key line of code. Hopefully this will fix the above problems in Couture.

  • tetchi
    tetchi on February 9th, 2012

    @Yasuko @Brian @mkengi shoot me an email and I’ll see what I can do! I’m just fixing up some of the code in this article, so I may not be able to get to you right away.

  • Yasuko
    Yasuko on February 11th, 2012

    tetchi, my site works good!
    thank you for you help!

  • tetchi
    tetchi on February 12th, 2012

    @Yasuko No worries!! :)

  • Ivete
    Ivete on February 24th, 2012

    Thank you for this tutorial, it worked beautifully! I’m in the process of deciding whether or not to switch to Shopify from a WordPress cart and this particular feature is something i really wanted, so your tutorial is a +1 for Shopify for me ;o)

  • tetchi
    tetchi on February 24th, 2012

    haha sweet! That’s what I like to hear :)

  • Mark Dunkley
    Mark Dunkley on February 24th, 2012

    Really great tutorial. Thanks Tets!

  • tetchi
    tetchi on February 25th, 2012

    Thanks Mark!

  • Brad
    Brad on February 28th, 2012

    Awesome post, Tets!

    I’ve included this new feature in the Responsive theme based on your tutorial.

  • colin
    colin on February 28th, 2012

    Great article tetchi!

    Last year I had a client that asked for this functionality but also wanted clicking on the thumbnail to change the selected variant.

    I made them upload images with the option names in the filename. This also makes sense when you look at the files on their filesystem so they didn’t mind.

    Anyways, I thought I would post it up to my github (https://github.com/cmcdonaldca/Shopify.VariantImages.js) and maybe someone will take the best of both. Or just use yours… which is great as it is!

    Colin

  • Tony
    Tony on February 28th, 2012

    Hi guys.

    I am trying to get this working but do not understand where to put this code. I’m not an expert but I know the basics and my way around code so I’m hoping I could implement this feature myself with your help.

    I am using the monochrome theme and searched my product.liquid file for the text you mentioned above to replace the code to hide the thumbnails but I cannot find anything with ‘<ul id="thumbs"' in there. Am I looking at the wrong file?

    Could you guys let me know how to do this step by step with Monochrome? I appreciate ANY help you can give me with this.

    Thank you!

  • Tony
    Tony on February 28th, 2012

    UPDATE: I added 2 different colors with “Create a new variant’ and I see the two options in a drop down on the product page however it still doesn’t seem to be working. For the variants I am setting the color as the title… am I doing this correctly? I notice in the screen shot you have ‘COLOR’ and than the colors under that but I am not sure sure how this was done as I am unable to create ‘Sub-variants’ under the title… unless I am missing something?

    I am not sure if that is wrong or if the code is. Here’s is what the area of my product.liquid looks like. I appreciate any help you can offer.

    {{ product.description }}

    ‹ See more {{ product.type | link_to_type }}.

    {% assign option_to_match = ‘Color’ %}
    {% assign option_index = 0 %}
    {% for option in product.options %}
    {% if option == option_to_match %}
    {% assign option_index = forloop.index0 %}
    {% endif %}
    {% endfor %}

    // <![CDATA[
    var selectCallback = function(variant, selector) {
    if (variant && variant.available == true) {

    var optionValue = variant.options[{{ option_index }}];
    var imageSrc = $("#thumbs img[alt='"+optionValue+"']").attr('src');
    if (imageSrc != 'undefined') {
    //Change '_thumb' with the image size that you are using for the thumbnails
    imageSrc = imageSrc.replace('_thumb','');
    $('#active-wrapper img').attr('src', imageSrc);
    }

  • tetchi
    tetchi on February 28th, 2012

    @Brad: Awesome! I’m honoured :) Your theme friggin rules!

    @Colin: Awesome implementation, using filename makes a lot of sense. I need to do what you and Caro do and put my stuff on Github!

    @Tony: Please shoot me and email at tetsuro at shopify.com, and I can help you out.

  • Kat
    Kat on February 28th, 2012

    Hello! Thank you so much for this – it’s just the feature I needed! I was wondering if there was a way to have the correct thumbnail image reflected in the cart so that it shows the selected variant? Right now, the thumbnail in the cart defaults to the featured image of the product page…

    Thank you!

  • tetchi
    tetchi on February 29th, 2012

    @Kat Unfortunately not right now, I will work on a solution when I have time!

  • John Reinhard
    John Reinhard on February 29th, 2012

    @Colin: Thank you for posting your approach! I read through your readme but I can’t figure out test steps

    1) include the script in your layout template
    {{ ‘shopify.variantimages.js’ | asset_url | script_tag }}

    ? – Do I insert this line into theme.liquid. If so can I put it anywhere?

    2) Copy this right before the “new Shopify.OptionSelectors(” line.

    ? – In what file / asset am I looking for the “new Shopify.OptionSelectors(” line? I did a search in theme.liquid but could not find the line of code there.

    Thanks – I still a rookie but I take instruction well.

    @Tetchi – Thanks for sharing your insight and getting this started. If anyone needs to know how to build a surfboard then feel free to ask me :)

  • Brad
    Brad on March 1st, 2012

    @Kat: I’m using this snippet for displaying the associated product image in the cart https://gist.github.com/1946527

  • Ryan
    Ryan on March 17th, 2012

    This is a great solution – Thanks for posting this! I have one question…it seems that it works great for all product images with a Alt Tag. But for products with no variants that don’t need an Alt Tag…it seems to conflict with the functionality of the rest of the page. For instance, the images don’t even load and the main menu drop-down navigation does not work. It seems that an Alt Tag for the Featured Image is mandatory, or it breaks functionality. Any help would be greatly appreciated!

  • Andrew
    Andrew on March 19th, 2012

    One huge issue I’m having (as is your demo) is getting the zoom functionality working after selecting an option. I’m using cloud-zoom on my project..would love anyone who has an idea how to accomplish. Great work so far!

  • Kristen
    Kristen on March 22nd, 2012

    Thank you so much! Exactly the info I needed :)

  • Jeff
    Jeff on April 17th, 2012

    This is great, thanks very much.

    One question though. I’ve implemented this successfully for products with a variant named Color. For products without a variant, the price no longer displays on the product details page.

    How can I have the price display for all products whether they have variants or not?

  • Jeff
    Jeff on April 17th, 2012

    I think I may have solved my earlier question by adding a conditional statement into the javascript code

    I first went about alerting the value of optionValue on all pages which returned a value of Default Title for products without variants.

    I then inserted the if statement into the second line of js:

    var optionValue = variant.options[{{ option_index }}];
    if(optionValue != ‘Default Title’) {
    var imageSrc = $(“#thumbs img[alt='”+optionValue+”‘]”).attr(‘src’);
    if (imageSrc != ‘undefined’) {
    //Change ‘_thumb’ with the image size that you are using for the thumbnails
    imageSrc = imageSrc.replace(‘_thumb’,”);
    $(‘#active-wrapper img’).attr(‘src’, imageSrc);
    }
    }

    Seems to be working well. Hope this helps out someone else. Cheers!

  • giorgia
    giorgia on April 19th, 2012

    Hi, I am working with the free trial, and I am going to get the Adaptable template.
    I’d like to know if there is the chance to apply this feature product by product. In other words, can i select to which products I want to upload this feature?
    thanks

  • Mandy
    Mandy on April 21st, 2012

    Thank you. That’s super nice of you to share this info. Any chance you would be able to do a tutorial using the Radiance theme to show how you could turn that template to sell one off items. For example, when a customer clicks buys and goes through the pay pal process, I’d like it to show on the website that the product is sold. Is it possible to add in code to this theme to enable this function for products that one off items? What would you advise? Cheers from NZ ;-)

  • Dave F
    Dave F on May 4th, 2012

    This is simply fantastic! I have been able to get it to work without a hitch (so far) but did have a quick question that I am hoping one of you rockstars can help me with.

    It appears as though this code overrides the “featured” image on the product page and displays the image associated with the first color listed. Basically what I am getting at is, I have a detail image of each my products (not associated with any variant) that I would still like to display as the “featured” image. Is this possible?

    Any help would be greatly appreciated!

  • Craig
    Craig on May 22nd, 2012

    I have the theme minimal, but I am having no luck getting the function to work. I have tried to reset the product variants and product images, nothing. The site still runs the same after cut and paste of the new code. Has anyone tried to hot wire this to the minimal theme. Do you Rockstars have any suggestions. Thanks.

  • Shane
    Shane on June 28th, 2012

    Any chance we can inject the SKU instead of the option name? I’ve been trying to merge this functionality along with Caroline Schnapp’s (there is a forum post from her on how to grap the sku with jQuery).

  • David
    David on August 2nd, 2012

    This tutorial is awesome, thanks very much. I was able to implement it and the snippet @Brad references above (to pass the color thumb to the cart page) with no problems.

    The only issue is what @Jeff is experiencing. On product pages where I have a single item that doesn’t have a color variant, the price does not display. My workaround is to add a color variant and alt tag to those single items, but that is going to be a pain for my client to remember to do that when adding one-off products. Jeff’s solution did not seem to work for me either.

    Has anyone figured out why the price disappears on a product that does not have a color variant and alt tag on the image?

    Thanks!

  • Josh
    Josh on August 29th, 2012

    Hey Tetchi!

    This blog is great and did help me on the Default theme for Shopify, but now that i have changed to the “Clearflex” Theme (lighthouse version), I am unable to locate the “selectCallback” in either file association you mentioned. Am I missing something?

    Could you help a n jsquery novice like myself understand better how to use the change() method? Where do i implement this js code if my theme does not use “selectCallback”?

    Appreciate it!
    Josh

  • Josh
    Josh on August 29th, 2012

    PS: password is “skeelt”

  • dave
    dave on September 12th, 2012

    Great work guys!

    @Colin: killer script

  • Marianne
    Marianne on September 12th, 2012

    Hi,

    I am trying to get the right image to show up when people select a color variation for my products using the New Standard theme which already has the selectCallback function. I am a half-noob with coding but handdled the various necesary changes quite allright so far.

    I followed instructions given above, change all ALT tags to correspond to my 10 color option names, found the different parts in the product.liquid code and edited as explained.

    When I do all these changes, on the site I no longer have any product image showing up nor the little box to choose from the available options (Even my logo and top menu disappear when I am on the product page). I tried various edits using pieces of codes that were posted above, sometimes I got my images and thumbs back on the screen but without the select color box.

    After edits following the above pattern, my product.liquid code from lines 236 to 272 looks like it (I replaced “Your Option Name Here” by “Title” because this is what it shows on the left side of SKU on my product document):

    // OPTION SELECT
    {% if product.variants.size > 1 %}

    {% assign look_for_image_match = false %}
    {% assign option_index = 0 %}
    {% for option in product.options %}
    {% assign downcased_option = option | downcase %}
    {% if downcased_option contains ‘color’ or downcased_option contains ‘colour’ or downcased_option contains ‘style’ %}
    {% assign look_for_image_match = true %}
    {% assign option_index = forloop.index0 %}
    {% endif %}
    {% endfor %}
    Shopify.doNotTriggerClickOnThumb = false;

    {% assign option_to_match = ‘Title’ %}
    {% assign option_index = 0 %}
    {% for option in product.options %}
    {% if option == option_to_match %}
    {% assign option_index = forloop.index0 %}
    {% endif %}
    {% endfor %}

    var selectCallback = function(variant, selector) {

    //Swapping images JS
    var optionValue = variant.options[{{ option_index }}];
    var imageSrc = $(“#thumbs img[alt='”+optionValue+”‘]”).attr(‘src’);
    if (imageSrc != ‘undefined’) {
    //Change ‘_thumb’ with the image size that you are using for the thumbnails
    imageSrc = imageSrc.replace(‘_thumb’,”);
    $(‘#active-wrapper img’).attr(‘src’, imageSrc);
    }

    if (variant && variant.available) {
    // selected a valid variant that is available.
    jQuery(‘#add’).removeClass(‘disabled’).removeAttr(‘disabled’).val(‘Lägg i varukorg’).fadeTo(200,1); // remove unavailable class from add-to-cart button, and re-enable button

    What am I doing wrong? Any advice / help / recommandation is welcome!
    /Marianne

  • Eloise
    Eloise on September 23rd, 2012

    Hi,
    I just launch different size options for my product and this is exactly what I was looking for. But like Yasuko & Brian I’m not using Radiance and just don’t understand how to implement step 2 and 3. I’m using Minimal theme. Your help would me very much appreciated!
    Thanks!

  • Zak Chamberlain
    Zak Chamberlain on November 1st, 2012

    Hi Mate, I have implemented your code. It doesn’t seems to be working. I have gone by step by step. I skipped hiding the thumbnails. But surely that wont effect the functionality? Any Suggestions?

    Cheers,

  • Kristy
    Kristy on November 8th, 2012

    I really want to add this feature to my website but am having the same trouble as a few others, I cannot find where put the code in correctly, and I am using the ENVY theme. Can somebody please help me out???

  • tetchi
    tetchi on November 10th, 2012

    Hey guys, check out the new Variant Images app here: http://apps.shopify.com/variant-images – it’s a much easier way to associate product images to variants!

  • Syed
    Syed on March 27th, 2015

    Hi Tetchi,

    is there any solution to display variant value display under each product image thumbnail??

    My client has flavors and they want me to display each flavor name under each product thumbnail on product page.. Please guide me direction…

    Best,
    Syed

  • The Smooth Shop
    The Smooth Shop on November 2nd, 2015

    Thanks for this tips. It had help us understand about this variant things with Shopify. I hope that things will be improved soon by shopify so that we will not be looking for other solutions for this problem.

  • Dawn
    Dawn on March 17th, 2017

    I just wanted to say I’m glad this still exists! I have a client with a pretty old theme (Minimo) that is impossible to find documentation on. Luckily this worked like a charm, once I realized I needed to change the image wrapper id. – Thanks for saving me huge re-development time.

  • Kyle
    Kyle on July 16th, 2017

    Hi Tetchi,

    Variant-image is not available in the app store of shopify, any means to get it?

    Thanks
    Kyle

  • tetchi
    tetchi on July 20th, 2017

    Hey Kyle, I’m sorry for the confusion, this post has not be updated in a while!

    Variant Images is now a native feature in Shopify. You can read more about it here: https://help.shopify.com/themes/customization/products/select-variants-by-clicking-images & https://help.shopify.com/manual/products/product-variant-images :)

Post a comment