I trust that you found this blog post to be enjoyable. If you are interested in having my team handle your eCommerce setup and marketing for you, Contact Us Click here.

Add Shopify Variant Images on Color Swatches

Shopify Variant Imges

Shopify doesn't offer image swatches by default in the variant picker. Adding shopify variant images to color swatches enhances product presentation and boosts conversions—just like major fashion brands do.

In this blog, we’ll walk you through how to add shopify custom image swatches to color variants in Dawn Theme using Liquid.

Step-by-Step Implementation

Step 1: Open Your Shopify Store

  • Log into your Shopify admin panel.
  • Go to Online Store → Themes.
  • Click “Edit code” for the theme you want to modify.

Step 2: Open main-product.liquid

  • Open the main-product.liquid file located in the Sections folder.
  • In the main-product.liquid file, scroll to the bottom to find the schema settings, or press Ctrl + F and search for "variant_picker" to locate it quickly.
  • In the variant picker settings, add a select option for image just below the button option.

{

   "value": "button",

   "label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.options__2.label"

 },

 {

   "value": "image",

   "label": "image"

 }

  • Add JS code in main-product.liquid.

<style>

  .hide-media{

    display:none;

    width:0

  }

</style>

<script>


  const handle = "products/" + "{{ product.handle }}" + ".js";


fetch(window.Shopify.routes.root + handle)

  .then(response => response.json())

  .then(product => {

    const optionsToWatch = "{{settings.media_grouping_option}}".split(",");

    const colorOption = product.options.find(option => optionsToWatch.includes(option.name))|| null;

    if (!colorOption) {

      console.log("No color options available for this product.");

      return;

    }

    // Retrieve color values

    const colorValues = colorOption.values;

    // Build an object to store the starting image positions for each color

    const colorImagePositions = {};

    

    colorValues.forEach(color => {

      // Find the first variant of this color and get its featured image position

      const variant = product.variants.find(variant => variant.options[colorOption.position - 1] === color);

      

      if (variant && variant.featured_media) {

        colorImagePositions[color] = variant.featured_media.position;

      }

    });    

    // Sort colors based on their starting positions to calculate image ranges

    const sortedColors = Object.entries(colorImagePositions).sort((a, b) => a[1] - b[1]);

    // Calculate ranges and log the result

    const colorImageRanges = {};

    sortedColors.forEach((color, index) => {

      const colorName = color[0];

      const startPos = color[1];

      const endPos = sortedColors[index + 1] ? sortedColors[index + 1][1] : null;

      

      colorImageRanges[colorName] = endPos ? [startPos, endPos] : [startPos];

    });

    // Build an object to store image IDs grouped by color based on colorImageRanges

    const colorImageIDs = {};

    Object.entries(colorImageRanges).forEach(([color, range]) => {

      const startPos = range[0];

      const endPos = range[1] || product.media.length +1; // If no end, assume range goes to the end of the images

      // Find all images within the range for this color

      const imageIDs = product.media

        .filter((media, index) => {

          const imagePosition = index + 1; // Adjust index to be position-based

          return imagePosition >= startPos && imagePosition < endPos;

        })

        .map(media => media.id); // Store the image ID


      colorImageIDs[color] = imageIDs;

    });

    const mediaGallery = document.querySelector('media-gallery');

    const productSection = document.querySelector(".product-variant-id")

    const sectionID = "{{ section.id }}"

    // Iterate over colorImageIDs to apply data-media-group based on the color ranges

    Object.entries(colorImageIDs).forEach(([color, imageIDs]) => {

      imageIDs.forEach(mediaID => {

        // Construct the selector for each media item using sectionID and media ID

        const selector = `[data-media-id="${sectionID}-${mediaID}"], [data-target="${sectionID}-${mediaID}"]`;

        // Find the image <li> and add the data-media-group attribute with the color

        const mediaItems = mediaGallery.querySelectorAll(`li${selector}`);

        mediaItems.forEach(mediaItem=>{

          mediaItem.setAttribute('data-media-group', color);

        })

      });

    });

  const showVariantImage = () => {

    const variantSelects = document.querySelector('variant-selects');

    // Get the currently selected color

    let currentValues = Array.from(

      variantSelects.querySelectorAll('select option[selected], fieldset input:checked')

    ).map(el => el.value);

    

    let selectedColor = currentValues.find(value => colorImageRanges.hasOwnProperty(value));

  

    // Show/Hide images based on selected color

    mediaGallery.querySelectorAll('ul li[data-media-group]').forEach((mediaItem, index) => {

      if (mediaItem.getAttribute('data-media-group') === selectedColor) {

        mediaItem.classList.remove('hide-media');

      } else {

        mediaItem.classList.add('hide-media');

      }

    });

  

    // Reinitialize the slider if needed

    mediaGallery.querySelectorAll('slider-component').forEach(slider => {

      slider.initPages();

    });

  }

    showVariantImage() 

    // Event listener to show/hide images based on the selected color

    productSection.addEventListener('change', showVariantImage); 

  })

  .catch(error => console.error("Error fetching product data:", error));

</script>

Step 3: Add schema settings for show selected variant images.

  • open settings_schema.json file from Config Folder.
  • Add this following settings.

{

    "name":"Media grouping option",

    "settings":[

      {

        "type": "text",

        "id": "media_grouping_option",

        "label": "Media grouping option",

        "default": "Color",

        "info":"Group variant media together and attach the first image of each group to a variant."

      },

      {

        "type": "paragraph",

        "content": "Only one option name at a time, if you need a different option name for specific products please create a new product page template."

      },

      {

        "type": "paragraph",

        "content": "If you have a multilingual store, you can enter multiple values separated by commas: Color,Colour,Farbe,Couleur"

      }

    ]

  },


Step 4: Open product-variant-options.liquid snippet.

  • Add the variant loop inside the value loop, just below this line:
  • {%- for value in option.values -%}

{%- assign variant_image = null -%}


{%- for variant in product.variants -%}

 {%- if variant.options contains value -%}

   {%- if variant.image -%}

     {%- assign variant_image = variant.image | image_url: width: 50 -%}

     {%- break -%}

   {%- endif -%}

 {%- endif -%}

{%- endfor -%}

  • Add the image picker type option in this file, just below the button picker type.

{%- elsif picker_type == 'image' -%}

<input

 type="radio"

 id="{{ input_id }}"

 name="{{ input_name | escape }}"

 value="{{ value | escape }}"

 form="{{ product_form_id }}"

 {% if value.selected %}

   checked

 {% endif %}

 {% if option_disabled %}

   class="disabled"

 {% endif %}

 {{ input_dataset }}

>

 <label for="{{ input_id }}" {% if variant_image != blank and option.name == 'Color' %} style="background-image: url({{ variant_image | img_url: '' }});height:40px;width:40px;background-size: cover;"{% else %}{{ value }} {%- endif -%}>

   {{ label_unavailable }}

   {% if option.name != 'Color' %}

     {{ value }}

   {% endif %}

 </label>

Step 5: Open product-variant-picker.liquid snippet.

  • Modify option loop and add picker type image.

{%- for option in product.options_with_values -%}

{%- liquid

 assign swatch_count = option.values | map: 'swatch' | compact | size

 assign picker_type = block.settings.picker_type


 if swatch_count > 0 and block.settings.swatch_shape != 'none'

   if block.settings.picker_type == 'dropdown'

     assign picker_type = 'swatch_dropdown'

   elsif block.settings.picker_type == 'image'

     assign picker_type = 'image'

   else

     assign picker_type = 'swatch'

   endif

 endif

  • Now add fieldset for image-type picker.

{%- elsif picker_type == 'image' -%}

<fieldset class="js product-form__input product-form__input--pill">

 <legend class="form__label">{{ option.name }}</legend>

 {% render 'product-variant-options',

   product: product,

   option: option,

   block: block,

   picker_type: picker_type

 %}

</fieldset>

{%- else -%}

Step 6: Align images and variants and assign images on variants in the products.

  • Go to the shopify admin panel and click on products.
  • Now open a product that has variants.
  • Upload product images in sequence.
  • Scroll down and click on variants to assign images on variants.

Step 7: Adjust Customizer settings of the store.

  • Open Customizer settings of the store
  • Go to the Default product page.
  • Select variant picker block under product information section.

  • Now in style Click on Dropdown and select Image option.

  • Check on store preview

Conclusion

Adding shopify image swatches to color variants makes product selection more visual and intuitive. It enhances user experience and gives your store a polished, professional look.

This small customization can lead to higher engagement and better conversions.

Back to blog

Are you interested in boosting your sales orders?

"PTI WebTech has a proven strategy to boost your sales. Contact us to learn more."

Conact Us

Newsletter

Subscribe our Newsletter for our blog posts and our new updates. Let's stay updated!

Our Latest Post