Tinker - Displaying only selected variant images

AI-generated summary

Shopify’s built-in “hide images of unselected variants” setting typically hides only the image assigned directly to each variant, not every gallery image for that colour. The store owner wants to show only the selected variant’s images and reduce page loads, noting that image filenames already contain variant slugs.

Suggested approaches include checking Tinker’s gallery settings or customizing the theme to filter images by variant. Several replies recommend tagging image alt text with the exact colour name, then showing matching images alongside untagged shared images; one reply provides a Tinker Custom Liquid example and setup steps. Another suggests matching filenames, but the implementation depends on the theme’s gallery structure and must update when customers change variants.

A key caveat is that merely hiding images may not prevent them from downloading, so genuine performance improvement requires loading only the selected group. A variant-image app was also suggested as an alternative. The owner thanked respondents and said they would handle the fix, but no completed implementation or confirmed resolution was reported.

Hi,

On my store, I have garments with 2+ images per variant. I’ve turned on the option to hide images of unselected variants, but it only applies to the variant’s main image. As a result, my product gallery shows two images of the selected variant and a lot of images from other variants.

Is there an option to display only the images of the selected variant? My image file names include the variant slug, so filtering should be fairly easy.

I really need this, as it’s killing my performance by downloading 20+ images :grimacing:

Hi @janekkmn Welcome To Shopify Community So What you’re seeing matches how the native setting works: Shopify only ties one featured image to each variant, so the “hide other variants’ media” toggle hides down to that one image and leaves the rest of the gallery alone. Showing a full set of images per variant isn’t in the data model, so it comes down to the theme. Some themes have their own media grouping setting for this, so check your theme’s product section settings first. If yours doesn’t, the usual route is a small custom filter. Tag each image’s alt text with the exact option value (for example the colour name), then in the gallery loop show only the images whose alt text matches the selected variant, plus any untagged shared images. You said your file names already include the variant slug, so matching on that could work too, but alt text is more reliable. Two notes: the filter has to run again when the variant changes, not only on first load, and for the performance problem, make sure images from other variants aren’t loaded until they’re needed, otherwise you still download the 20+ files. If you share your theme name, someone can point you to the right file for the gallery loop. please do not forget to like and mark it solution
Best Mustufa

Hi @janekkmn

Here is a free way to show only the selected colour’s images, plus any shared ones. It works on Tinker with no app.

  1. Go to Products and open your product.
  2. Click the first image of a colour.
  3. In Alt text, type the colour name exactly as in your variant (for example White) and save.

  1. Repeat for every image of that colour. Leave shared images (size chart, lifestyle) empty.
  2. Go to Online Store > Themes and click Customize on Tinker.
  3. Open a product page and click Product information in the left list.
  4. Scroll to the bottom, click Add block and choose Custom Liquid.

  1. Paste this code into the Custom Liquid box:
{%- liquid
  assign vf_options = closest.product.options_with_values
-%}
<script>
(function () {
  if (window.__variantMediaFilter) return;
  window.__variantMediaFilter = true;

  var OPTIONS = [
    {%- for o in vf_options -%}
      { "values": [ {%- for v in o.values -%}{%- assign vn = v.name | default: v -%}{{ vn | json }}{%- unless forloop.last -%},{%- endunless -%}{%- endfor -%} ] }{%- unless forloop.last -%},{%- endunless -%}
    {%- endfor -%}
  ];
  if (!OPTIONS.length) return;

  var norm = function (s) { return (s || '').toLowerCase().trim(); };

  function gallerySection() {
    var g = document.querySelector('media-gallery');
    return (g && g.closest('.shopify-section')) || document.body;
  }

  // Pick the option whose values best match the images' Alt text (auto-detects "Color").
  function pickOption(section) {
    var alts = [].map.call(section.querySelectorAll('.product-media img'), function (i) {
      return norm(i.getAttribute('alt'));
    });
    var best = null, bestScore = 0;
    OPTIONS.forEach(function (o) {
      var score = o.values.filter(function (v) {
        var lv = norm(v);
        return lv && alts.some(function (a) { return a.indexOf(lv) > -1; });
      }).length;
      if (score > bestScore) { bestScore = score; best = o; }
    });
    return best;
  }

  function selectedValue(section, values) {
    var vals = values.map(norm);
    var r = [].filter.call(section.querySelectorAll('input:checked'), function (i) {
      return vals.indexOf(norm(i.value)) > -1;
    })[0];
    if (r) return norm(r.value);
    var s = [].filter.call(section.querySelectorAll('select'), function (el) {
      return vals.indexOf(norm(el.value)) > -1;
    })[0];
    return s ? norm(s.value) : null;
  }

  function box(m) { return m.closest('slideshow-slide') || m.closest('li') || m; }

  function apply() {
    var section = gallerySection();
    var opt = pickOption(section);
    if (!opt) return;
    var values = opt.values.map(norm);
    var selected = selectedValue(section, opt.values);
    if (!selected) return;

    var medias = section.querySelectorAll('.product-media');
    var visible = 0;
    [].forEach.call(medias, function (m) {
      var img = m.querySelector('img');
      var alt = norm(img && img.getAttribute('alt'));
      var mentions = values.filter(function (v) { return v && alt.indexOf(v) > -1; });
      var show = mentions.length === 0 || mentions.indexOf(selected) > -1;
      var el = box(m);
      el.style.display = show ? '' : 'none';
      el.hidden = !show;
      if (show) visible++;
    });
    if (!visible) { // fail-safe: never blank the gallery
      [].forEach.call(medias, function (m) { var el = box(m); el.style.display = ''; el.hidden = false; });
    }
  }

  function boot() {
    var section = gallerySection();
    apply();
    section.addEventListener('change', function () { setTimeout(apply, 60); });
    new MutationObserver(function (muts) {
      for (var i = 0; i < muts.length; i++) {
        if (muts[i].addedNodes && muts[i].addedNodes.length) { apply(); return; }
      }
    }).observe(section, { childList: true, subtree: true });
  }

  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
  else boot();
})();
</script>
  1. Click Save.

Pick another colour on the product page. Only that colour’s images stay.

Hi, Have you been able to fix this issue now?

Hi @janekkmn

Yes, this is possible with a custom theme code solution.

Shopify’s default “Hide images of unselected variants” setting may only hide images directly associated with variants, rather than filtering the entire gallery based on the selected variant.

Since your image filenames already include the variant slug, you can use JavaScript to:

  1. Detect the currently selected variant whenever a customer changes an option.
  2. Extract the variant slug from the selected variant’s information
  3. Compare that slug with the image filenames or image alt text.
  4. Display only the images matching the selected variant.
  5. Update the gallery dynamically without reloading the page.

You should also ensure that hidden images are not unnecessarily loaded, using lazy loading where appropriate. This can help reduce unnecessary image downloads and improve product page performance.

One important point: the implementation depends on your Shopify theme’s product gallery structure and how it handles variant changes. I’d recommend implementing this directly in the theme rather than relying on the default setting.

Best regards,
Devcoder :laptop:

Thank you for all answers, they are helpful. I will handle this :slight_smile:

Hi @janekkmn :blush:

Shopify’s built-in option to hide images of unselected variants doesn’t necessarily filter every image associated with a variant. It generally relies on the variant’s assigned image, so products with multiple images per colour can require additional theme customization.

Since your image filenames already contain the variant slug, you have a useful starting point. One approach would be to customize the product gallery so it groups images by variant and updates the visible group whenever a customer selects a different variant.

You could use the filename convention as the basis for matching, although the theme may need to expose that information through image alt text or another identifier, depending on how its gallery is built.

One important distinction: simply hiding the other images with CSS may not solve the performance issue, because the browser could still download them. The gallery would need to load only the selected variant’s images, rather than loading all images and hiding some afterward.

I’d check how your theme currently loads product media before making changes. The exact implementation will depend on the theme and its gallery JavaScript.

Hi @janekkmn, Mustafa is right that Shopify links only one image to each variant, so the theme setting can’t hide the rest. If you’d rather not edit theme code, a variant image app can group all photos per variant and load only the selected set, which also helps your page speed. Disclosure: I work at Orichi, and our app Swatchy does this. Happy to check it on your Tinker theme for free before you commit. Either way, the alt-text approach above works too.