How to display specific images for each product variant in Shopify

Home » Articles » Shopify » How to display specific images for each product variant in Shopify

Are you struggling with product images showing up for the wrong variants in your Shopify store? Here’s a simple guide to help you display only the relevant images for each product variation, such as different colours of a t-shirt.

Steps by steps instructions

To get the job done, follow each step below

Preparing your images

  1. Group your product images by colour or variant.
  2. Ensure the order of these groups matches your variant values (e.g., green, yellow).
  3. Attach a featured image to each variant.
  4. Make the featured image for each colour the first in its group.

Installing the necessary code

  1. Duplicate your theme (ensure it’s a free theme like Dawn).
  2. Click ‘Edit code’ on the duplicated theme.
  3. Open the ‘config’ folder and edit the ‘settings_schema.json’ file.
  4. Paste the required code snippet after the opening bracket and save your changes.
  {
    "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"
      }
    ]
  },

Adding a custom liquid block

  1. Open the theme customiser and go to a product page.
  2. Add a new custom liquid block in the product information section.
  3. Paste the second code snippet into the custom liquid settings.
<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_image) {
        colorImagePositions[color] = variant.featured_image.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>

Adjusting media grouping settings

  1. In the customiser, click the gear icon.
  2. Select ‘Media grouping option’.
  3. Adjust the option name if needed (e.g., ‘colour’ for UK spelling).
  4. For multilingual stores, enter multiple values separated by commas.

Troubleshooting

If you can’t see the first gallery thumbnail:

  1. Click on the product information section.
  2. Find ‘Hide other variants media after selecting a variant’.
  3. Enable or disable this option based on your theme version.

Applying to specific products

To use this feature only for certain products:

  1. Create a new product page template with the custom liquid block.
  2. Remove the block from the default template.

Wave

Enjoy our articles? Join our free list and get more.

Sign Up

Book Discovery Call