Update a theme to use variant images

Variant images is a feature that allows you to associate an image with a variant. This article outlines how to update your theme to take advantage of this feature.

Updating product.liquid to support variant deep-linking

One component of the variant images feature is the ability to deep-link directly to a variant. This is done by appending the ?variant= query parameter to the URL of the product along with the ID of the variant.

For example, if you wanted to link to the "Small" variant of a T-shirt, you could do so through a URL that looks like this:


We can use Liquid to output the attributes of the deep-linked variant when the product.liquid template is loaded.

Selecting the variant in the option drop-down

In your theme, you may have a select menu for product options that looks like this:

  {% for variant in product.variants %}
    <option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
  {% endfor %}

To have the product.liquid template automatically select the deep-linked variant, use the following code:

  {% for variant in product.variants %}
    <option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
  {% endfor %}

Here, we are using the product.selected_or_first_available_variant attribute which returns the variant that was deep-linked. If it matches with the variant in the current iteration of the for loop, it will output selected="selected", causing that option in the drop-down to be selected when the template is loaded.

Showing the deep-linked variant's price

In your theme, you may be outputting the price of the variant as follows:

<div class="purchase">
  <h2 class="price" id="price-preview">{{ product.price_min | money }}{% if product.price_min < product.compare_at_price_min %} <del>{{ product.compare_at_price_min | money }}</del>{% endif %}</h2>

To ensure that the price of the deep-linked variant is output, use the product.selected_or_first_available_variant attribute as shown below:

<div class="purchase">
  <h2 class="price" id="price-preview">{{ product.selected_or_first_available_variant.price | money }}{% if product.selected_or_first_available_variant.price < product.selected_or_first_available_variant.compare_at_price %} <del>{{ product.selected_or_first_available_variant.compare_at_price | money }}</del>{% endif %}</h2>

Showing the deep-linked variant's image

To show the deep-linked variant's image in the "featured image" container when the product page is loaded, you must replace the product's featured image with the image of the variant returned by the product.selected_or_first_available_variant attribute.

In your theme, you may be loading the product's featured image like this:

<a href="{{ product.featured_image | product_img_url: '2048x' }}" >
  <img src="{{ product.featured_image | product_img_url: '2048x' }}" />

Replace this with the code below:

{% assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image %}
<a href="{{ featured_image | img_url: '2048x' }}" >
  <img src="{{ featured_image | img_url: '2048x' }}" alt="{{ featured_image.alt | escape }}" />

Here, we use the product.selected_or_first_available_variant attribute to select the deep-linked variant, then access its featured_image attribute to output its image. The default filter is used to select the product's featured_image if a variant image does not exist.

Updating product.liquid to support variant images

In Step 1 we added Liquid code to show the appropriate attributes of the deep-linked variant. However, after the page is loaded, we must update the OptionSelectors Javascript function to update the variant image as the user selects different variants.

Updating the OptionSelectors JavaScript function

The JavaScript for OptionSelectors is typically found in the product.liquid or theme.liquid template. It may also be inside a separate JavaScript file in theme's Theme Assets.

Look for where OptionSelectors is initialized, and add enableHistoryState: true to its parameter, as follows:

new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });

Adding this new parameter to the OptionSelectors constructor makes it so that the URL in the browser updates with the ?variant=variant_id query parameter as you select different variants.

Next, we want to have the product page image update with the variant's image as you select different variants. In the selectCallback function, you will likely already have some code that updates the variants' price, compare_at_price, etc. Within the selectCallback function, add the following code:

var selectCallback = function(variant, selector) {
  if (variant) {
    if (variant.available) {
    else {
  else {
  if (variant && variant.featured_image) {
    var originalImage = $(".featured-image-div img");
    var newImage = variant.featured_image;
    var element = originalImage[0];
    Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
      $(element).parents('a').attr('href', newImageSizedSrc);
      $(element).attr('src', newImageSizedSrc);

Don't forget to replace .featured-image-div with the class or id of the element wrapping the featured image in your theme.

Preloading images

You may want to preload your images so there is no delay or flicker when they are switched. To do so, simply call this function after you have included option_selection.js:

Shopify.Image.preload({{ product.images | json }}, '1024x1024');

Updating cart.liquid

Displaying the variant image

To display the variant image on the cart page, look for where you're outputting the featured_image attribute of the line item variable:

<img src="{{ item.featured_image | product_img_url: 'small' }}"  alt="{{ item.title | escape }}" />

... and replace it with the following:

<img src="{{ item | img_url: 'small' }}"  alt="{{ item.title | escape }}" />

The img_url filter looks for the item's variant image, otherwise it defaults to the item's featured image.

Linking to the variant

The line item title in the cart page typically links to the product page. Since the line item is aware of what variant was added to the cart, it should deep-link to the product's variant instead.

To do this, replace the product.url attribute of the line item...

<a href="{{ item.product.url }}">
<!-- Output: http://example.myshopify.com/products/example-product -->

... with url.

<a href="{{ item.url }}">
<!-- Output: http://example.myshopify.com/products/example-product?variant=105065082 -->

Ready to start selling with Shopify?

Try it free