Shopify Tutorial: How to Display Only Selected Variant Images

Author: Sonya

12-24-2024 8:44 AM

Recently, a Shopify store owner approached us with a specific requirement: they wanted to showcase only the images of the selected variant in their product gallery. This need arose from having multiple variants for a single product, each with its own set of images. By displaying only the relevant images, the store owner aimed to streamline the user experience, allowing customers to focus on the variant they were interested in without distraction.

Benefits of Displaying Only Selected Variant Images

Implementing this feature can significantly enhance your store's functionality and user experience. Here are some key advantages:

  • Improved User Experience: Customers can easily view and compare images of the selected variant without being overwhelmed by irrelevant images.

  • Enhanced Visual Appeal: A cleaner and more organized product gallery makes your store visually appealing, encouraging customers to explore further.

  • Increased Conversion Rates: Simplifying product presentation helps customers make informed purchasing decisions, potentially boosting conversion rates.

Steps to Implement Selected Variant Images in Shopify

Before making any code modifications, always ensure you create a copy of the theme first. Test all your changes on this copy to confirm everything works perfectly before publishing it to the live theme. This precaution helps prevent any issues from affecting your main theme and keeps your work safe.

To display only the images of the selected variant in your Shopify store, follow these straightforward steps:

  1. Access Your Theme Code Editor: Log into your Shopify admin panel and navigate to "Online Store" > "Themes." Click on "Actions" and select "Edit code" for your active theme.

  2. Modify sections/main-product.liquid: Open the sections/main-product.liquid file. Add below code to the file.

    ,
        {
          "type": "header",
          "content": "Selected Variant Images"
        },
        {
            "type": "paragraph",
            "content": "Subscribe our channel [Shinetech ChangChun](https:\/\/youtube.com\/@ShinetechShopidev?sub_confirmation=1)"
        },
        {
          "type": "checkbox",
          "id": "enable_group_media",
          "label": "Enable Selected Variant Images",
          "default": false
        }
  3. Update snippets/product-media-gallery.liquid: Locate and open the snippets/product-media-gallery.liquid file. Replace the existing code with code below.

    
    {% comment %}
      Renders a product media gallery. Should be used with 'media-gallery.js'
      Also see 'product-media-modal'
    
      Accepts:
      - product: {Object} Product liquid object
      - variant_images: {Array} Product images associated with a variant
      - limit: {Number} (optional) When passed, limits the number of media items to render
    
      Usage:
      {% render 'product-media-gallery' %}
    {% endcomment %}
    
    {%- liquid
      if section.settings.hide_variants and variant_images.size == product.media.size
        assign single_media_visible = true
      endif
    
      if limit == 1
        assign single_media_visible = true
      endif
    
      assign media_count = product.media.size
      if section.settings.hide_variants and media_count > 1 and variant_images.size > 0
        assign media_count = media_count | minus: variant_images.size | plus: 1
      endif
    
      if media_count == 1 or single_media_visible
        assign single_media_visible_mobile = true
      endif
    
      if media_count == 0 or single_media_visible_mobile or section.settings.mobile_thumbnails == 'show' or section.settings.mobile_thumbnails == 'columns' and media_count < 3
        assign hide_mobile_slider = true
      endif
    
      if section.settings.media_size == 'large'
        assign media_width = 0.65
      elsif section.settings.media_size == 'medium'
        assign media_width = 0.55
      elsif section.settings.media_size == 'small'
        assign media_width = 0.45
      endif
    -%}
    
    <media-gallery
      id="MediaGallery-{{ section.id }}"
      role="region"
      {% if section.settings.enable_sticky_info %}
        class="product__column-sticky"
      {% endif %}
      aria-label="{{ 'products.product.media.gallery_viewer' | t }}"
      data-desktop-layout="{{ section.settings.gallery_layout }}"
    >
      <div id="GalleryStatus-{{ section.id }}" class="visually-hidden" role="status"></div>
      <slider-component id="GalleryViewer-{{ section.id }}" class="slider-mobile-gutter">
        <a class="skip-to-content-link button visually-hidden quick-add-hidden" href="#ProductInfo-{{ section.id }}">
          {{ 'accessibility.skip_to_product_info' | t }}
        </a>
        <ul
          id="Slider-Gallery-{{ section.id }}"
          class="product__media-list contains-media grid grid--peek list-unstyled slider slider--mobile"
          role="list"
        >
          {%- if product.selected_or_first_available_variant.featured_media != null -%}
            {%- assign featured_media = product.selected_or_first_available_variant.featured_media -%}
            <li
              id="Slide-{{ section.id }}-{{ featured_media.id }}"
              class="product__media-item grid__item slider__slide is-active{% if single_media_visible %} product__media-item--single{% endif %}{% if featured_media.media_type != 'image' %} product__media-item--full{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--fade-in{% endif %}"
              data-media-id="{{ section.id }}-{{ featured_media.id }}"
            >
              {%- assign media_position = 1 -%}
              {% render 'product-thumbnail',
                media: featured_media,
                media_count: media_count,
                position: media_position,
                desktop_layout: section.settings.gallery_layout,
                mobile_layout: section.settings.mobile_thumbnails,
                loop: section.settings.enable_video_looping,
                modal_id: section.id,
                xr_button: true,
                media_width: media_width,
                media_fit: section.settings.media_fit,
                constrain_to_viewport: section.settings.constrain_to_viewport,
                lazy_load: false
              %}
            </li>
          {%- endif -%}
          {%- for media in product.media -%}
            {% if media_position >= limit
              or media_position >= 1
              and section.settings.hide_variants
              and variant_images contains media.src
            %}
              {% continue %}
            {% endif %}
            {%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
                {%- liquid
                  assign media_position = media_position | default: 0 | plus: 1
                  assign lazy_load = false
                  if media_position > 1
                    assign lazy_load = true
                  endif
                  assign current_color = product.selected_or_first_available_variant.option1              
                -%}
                {% if section.settings.enable_group_media == false or media_count == 1 or current_color == media.alt and section.settings.enable_group_media == true  %}
              <li
                id="Slide-{{ section.id }}-{{ media.id }}"
                class="product__media-item grid__item slider__slide{% if single_media_visible %} product__media-item--single{% endif %}{% if product.selected_or_first_available_variant.featured_media == nil and forloop.index == 1 %} is-active{% endif %}{% if media.media_type != 'image' %} product__media-item--full{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--fade-in{% endif %}"
                data-media-id="{{ section.id }}-{{ media.id }}"
              >
                {% render 'product-thumbnail',
                  media: media,
                  media_count: media_count,
                  position: media_position,
                  desktop_layout: section.settings.gallery_layout,
                  mobile_layout: section.settings.mobile_thumbnails,
                  loop: section.settings.enable_video_looping,
                  modal_id: section.id,
                  xr_button: true,
                  media_width: media_width,
                  media_fit: section.settings.media_fit,
                  constrain_to_viewport: section.settings.constrain_to_viewport,
                  lazy_load: lazy_load
                %}
               
              </li>
                   {% endif %}
            {%- endunless -%}
          {%- endfor -%}
        </ul>
        <div class="slider-buttons quick-add-hidden{% if hide_mobile_slider %} small-hide{% endif %}">
          <button
            type="button"
            class="slider-button slider-button--prev"
            name="previous"
            aria-label="{{ 'general.slider.previous_slide' | t }}"
          >
            {% render 'icon-caret' %}
          </button>
          <div class="slider-counter caption">
            <span class="slider-counter--current">1</span>
            <span aria-hidden="true"> / </span>
            <span class="visually-hidden">{{ 'general.slider.of' | t }}</span>
            <span class="slider-counter--total">{{ media_count }}</span>
          </div>
          <button
            type="button"
            class="slider-button slider-button--next"
            name="next"
            aria-label="{{ 'general.slider.next_slide' | t }}"
          >
            {% render 'icon-caret' %}
          </button>
        </div>
      </slider-component>
      {%- if first_3d_model -%}
        <button
          class="button button--full-width product__xr-button"
          type="button"
          aria-label="{{ 'products.product.xr_button_label' | t }}"
          data-shopify-xr
          data-shopify-model3d-id="{{ first_3d_model.id }}"
          data-shopify-title="{{ product.title | escape }}"
          data-shopify-xr-hidden
        >
          {% render 'icon-3d-model' %}
          {{ 'products.product.xr_button' | t }}
        </button>
      {%- endif -%}
      {%- liquid
        assign is_not_limited_to_single_item = false
        if limit == null or limit > 1
          assign is_not_limited_to_single_item = true
        endif
      -%}
      {%- if is_not_limited_to_single_item
        and media_count > 1
        and section.settings.gallery_layout contains 'thumbnail'
        or section.settings.mobile_thumbnails == 'show'
      -%}
        <slider-component
          id="GalleryThumbnails-{{ section.id }}"
          class="thumbnail-slider slider-mobile-gutter quick-add-hidden{% unless section.settings.gallery_layout contains 'thumbnail' %} medium-hide large-up-hide{% endunless %}{% if section.settings.mobile_thumbnails != 'show' %} small-hide{% endif %}{% if media_count <= 3 %} thumbnail-slider--no-slide{% endif %}"
        >
          <button
            type="button"
            class="slider-button slider-button--prev{% if media_count <= 3 %} small-hide{% endif %}{% if media_count <= 4 %} medium-hide large-up-hide{% endif %}"
            name="previous"
            aria-label="{{ 'general.slider.previous_slide' | t }}"
            aria-controls="GalleryThumbnails-{{ section.id }}"
            data-step="3"
          >
            {% render 'icon-caret' %}
          </button>
          <ul
            id="Slider-Thumbnails-{{ section.id }}"
            class="thumbnail-list list-unstyled slider slider--mobile{% if section.settings.gallery_layout == 'thumbnail_slider' %} slider--tablet-up{% endif %}"
          >
            {%- capture sizes -%}
              (min-width: {{ settings.page_width }}px) calc(({{ settings.page_width | minus: 100 | times: media_width | round }} - 4rem) / 4),
              (min-width: 990px) calc(({{ media_width | times: 100 }}vw - 4rem) / 4),
              (min-width: 750px) calc((100vw - 15rem) / 8),
              calc((100vw - 8rem) / 3)
            {%- endcapture -%}
    
            {%- if featured_media != null -%}
              {%- liquid
                capture media_index
                  if featured_media.media_type == 'model'
                    increment model_index
                  elsif featured_media.media_type == 'video' or featured_media.media_type == 'external_video'
                    increment video_index
                  elsif featured_media.media_type == 'image'
                    increment image_index
                  endif
                endcapture
                assign media_index = media_index | plus: 1            
              -%}          
              <li
                id="Slide-Thumbnails-{{ section.id }}-0"
                class="thumbnail-list__item slider__slide{% if section.settings.hide_variants and variant_images contains featured_media.src %} thumbnail-list_item--variant{% endif %}"
                data-target="{{ section.id }}-{{ featured_media.id }}"
                data-media-position="{{ media_index }}"
                data-alt="{{ media.alt }}"
              >
                {%- capture thumbnail_id -%}
                  Thumbnail-{{ section.id }}-0
                {%- endcapture -%}
                
                <button
                  class="thumbnail global-media-settings global-media-settings--no-shadow"
                  aria-label="{%- if featured_media.media_type == 'image' -%}{{ 'products.product.media.load_image' | t: index: media_index }}{%- elsif featured_media.media_type == 'model' -%}{{ 'products.product.media.load_model' | t: index: media_index }}{%- elsif featured_media.media_type == 'video' or featured_media.media_type == 'external_video' -%}{{ 'products.product.media.load_video' | t: index: media_index }}{%- endif -%}"
                  aria-current="true"
                  aria-controls="GalleryViewer-{{ section.id }}"
                  aria-describedby="{{ thumbnail_id }}"
                >
                  {{
                    featured_media.preview_image
                    | image_url: width: 416
                    | image_tag:
                      loading: 'lazy',
                      sizes: sizes,
                      widths: '54, 74, 104, 162, 208, 324, 416',
                      id: thumbnail_id,
                      alt: featured_media.alt
                    | escape
                  }}
                </button>
              </li>          
            {%- endif -%}
            {%- for media in product.media -%}
              {%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
                {%- liquid
                  capture media_index
                    if media.media_type == 'model'
                      increment model_index
                    elsif media.media_type == 'video' or media.media_type == 'external_video'
                      increment video_index
                    elsif media.media_type == 'image'
                      increment image_index
                    endif
                  endcapture
                  assign media_index = media_index | plus: 1
                -%}
                <li
                  id="Slide-Thumbnails-{{ section.id }}-{{ forloop.index }}"
                  class="thumbnail-list__item slider__slide{% if section.settings.hide_variants and variant_images contains media.src %} thumbnail-list_item--variant{% endif %}"
                  data-target="{{ section.id }}-{{ media.id }}"
                  data-media-position="{{ media_index }}"
                  data-alt="{{ media.alt }}"
                  data-enable-group-media="{{ section.settings.enable_group_media }}"
                >
                  {%- if media.media_type == 'model' -%}
                    <span class="thumbnail__badge" aria-hidden="true">
                      {%- render 'icon-3d-model' -%}
                    </span>
                  {%- elsif media.media_type == 'video' or media.media_type == 'external_video' -%}
                    <span class="thumbnail__badge" aria-hidden="true">
                      {%- render 'icon-play' -%}
                    </span>
                  {%- endif -%}
                  {%- capture thumbnail_id -%}
                    Thumbnail-{{ section.id }}-{{ forloop.index }}
                  {%- endcapture -%}
                  <button
                    class="thumbnail global-media-settings global-media-settings--no-shadow"
                    aria-label="{%- if media.media_type == 'image' -%}{{ 'products.product.media.load_image' | t: index: media_index }}{%- elsif media.media_type == 'model' -%}{{ 'products.product.media.load_model' | t: index: media_index }}{%- elsif media.media_type == 'video' or media.media_type == 'external_video' -%}{{ 'products.product.media.load_video' | t: index: media_index }}{%- endif -%}"
                    {% if media == product.selected_or_first_available_variant.featured_media
                      or product.selected_or_first_available_variant.featured_media == null
                      and forloop.index == 1
                    %}
                      aria-current="true"
                    {% endif %}
                    aria-controls="GalleryViewer-{{ section.id }}"
                    aria-describedby="{{ thumbnail_id }}"
                  >
                    {{
                      media.preview_image
                      | image_url: width: 416
                      | image_tag:
                        loading: 'lazy',
                        sizes: sizes,
                        widths: '54, 74, 104, 162, 208, 324, 416',
                        id: thumbnail_id,
                        alt: media.alt
                      | escape
                    }}
                  </button>
                 
                </li>
              {%- endunless -%}
            {%- endfor -%}
          </ul>
          <button
            type="button"
            class="slider-button slider-button--next{% if media_count <= 3 %} small-hide{% endif %}{% if media_count <= 4 %} medium-hide large-up-hide{% endif %}"
            name="next"
            aria-label="{{ 'general.slider.next_slide' | t }}"
            aria-controls="GalleryThumbnails-{{ section.id }}"
            data-step="3"
          >
            {% render 'icon-caret' %}
          </button>
        </slider-component>
      {%- endif -%}
    </media-gallery>
    
  4. Edit snippets/product-media-modal.liquid: Open this file and replace the code with below code.

    {% comment %}
      Renders a product media modal. Also see 'product-media-gallery'
    
      Accepts:
      - product: {Object} Product liquid object
      - variant_images: {Array} Product images associated with a variant
    
      Usage:
      {% render 'product-media-modal' %}
    {% endcomment %}
    
    <product-modal id="ProductModal-{{ section.id }}" class="product-media-modal media-modal">
      <div
        class="product-media-modal__dialog color-{{ section.settings.color_scheme }} gradient"
        role="dialog"
        aria-label="{{ 'products.modal.label' | t }}"
        aria-modal="true"
        tabindex="-1"
      >
        <button
          id="ModalClose-{{ section.id }}"
          type="button"
          class="product-media-modal__toggle"
          aria-label="{{ 'accessibility.close' | t }}"
        >
          {{ 'icon-close.svg' | inline_asset_content }}
        </button>
    
        <div
          class="product-media-modal__content color-{{ section.settings.color_scheme }} gradient"
          role="document"
          aria-label="{{ 'products.modal.label' | t }}"
          tabindex="0"
        >
          {%- liquid
            if product.selected_or_first_available_variant.featured_media != null
              assign media = product.selected_or_first_available_variant.featured_media
              render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: section.settings.hide_variants
            endif
          -%}
    
          {%- for media in product.media -%}
            {%- liquid
              if section.settings.hide_variants and variant_images contains media.src or variant_images contains media.id
                assign variant_image = true
              else
                assign variant_image = false
              endif
    
              unless media.id == product.selected_or_first_available_variant.featured_media.id
                render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: variant_image
              endunless
            -%}
          {%- endfor -%}
        </div>
      </div>
    </product-modal>
    
    
    
  5. Edit snippets/product-variant-picker.liquid: Open this file and replace the code with below code.

    {% comment %}
      Renders product variant-picker
    
      Accepts:
      - product: {Object} product object.
      - block: {Object} passing the block information.
      - product_form_id: {String} Id of the product form to which the variant picker is associated.
      Usage:
      {% render 'product-variant-picker', product: product, block: block, product_form_id: product_form_id %}
    {% endcomment %}
    {%- unless product.has_only_default_variant -%}
      <variant-selects
        id="variant-selects-{{ section.id }}"
        data-section="{{ section.id }}"
        {{ block.shopify_attributes }}
      >
        {%- 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'
              else
                assign picker_type = 'swatch'
              endif
            endif
          -%}
          {%- if picker_type == 'swatch' -%}
            <fieldset class="js product-form__input product-form__input--swatch" data-option-name="{{ option.name }}">
              <legend class="form__label">
                {{ option.name }}:
                <span data-selected-value>
                  {{- option.selected_value -}}
                </span>
              </legend>
              {% render 'product-variant-options',
                product: product,
                option: option,
                block: block,
                picker_type: picker_type
              %}
            </fieldset>
          {%- elsif picker_type == 'button' -%}
            <fieldset class="js product-form__input product-form__input--pill" data-option-name="{{ option.name }}">
              <legend class="form__label">{{ option.name }}</legend>
              {% render 'product-variant-options',
                product: product,
                option: option,
                block: block,
                picker_type: picker_type
              %}
            </fieldset>
          {%- else -%}
            <div class="product-form__input product-form__input--dropdown">
              <label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}">
                {{ option.name }}
              </label>
              <div class="select">
                {%- if picker_type == 'swatch_dropdown' -%}
                  <span
                    data-selected-value
                    class="dropdown-swatch"
                  >
                    {% render 'swatch', swatch: option.selected_value.swatch, shape: block.settings.swatch_shape %}
                  </span>
                {%- endif -%}
                <select
                  id="Option-{{ section.id }}-{{ forloop.index0 }}"
                  class="select__select"
                  name="options[{{ option.name | escape }}]"
                  form="{{ product_form_id }}"
                  data-option-name="{{ option.name }}"
                >
                  {% render 'product-variant-options',
                    product: product,
                    option: option,
                    block: block,
                    picker_type: picker_type
                  %}
                </select>
                <span class="svg-wrapper">
                  {{- 'icon-caret.svg' | inline_asset_content -}}
                </span>
              </div>
            </div>
          {%- endif -%}
        {%- endfor -%}
    
        <script type="application/json" data-selected-variant>
          {{ product.selected_or_first_available_variant | json }}
        </script>
      </variant-selects>
    {%- endunless -%}
  6. Update assets/product-info.js: In this file, add a new function called setVariantImages. Update the file Update the file with reference to the screenshots below.

    Update line 17 :

    this.setVariantImages()

    Update line 308 and 315:

    this.setVariantImages()
     setVariantImages() {
           // set variant images in the media gallery
            const galleryImages = Array.from(document.querySelectorAll('[data-alt]'));
            const variantOptionNames = Array.from(document.querySelectorAll('[data-option-name]'));
            let setVariantImages = false;
            let value;
            variantOptionNames.forEach((variantOption)=> {
              if(variantOption.getAttribute('data-option-name').toLowerCase() == 'color') {
                var inputs = variantOption.querySelectorAll('input');
                if (inputs.length)
                {
                  value = Array.from(variantOption.querySelectorAll('input')).find((radio) => radio.checked).value;
                } else {
                  value = variantOption.value;
                }
                
                setVariantImages = true;
              }
            })
            if(setVariantImages) {
              galleryImages.forEach((galleryImage) => {
                if((galleryImage.getAttribute('data-alt') == value || galleryImage.getAttribute('data-alt').toLowerCase() == 'public' ) && galleryImage.getAttribute('data-enable-group-media') == 'true') {
                  galleryImage.classList.remove("thumbnail-list_item--variant");            
                } else {
                  galleryImage.classList.add("thumbnail-list_item--variant");
                }          
              })
           }
          }
  7. Set Up Variant Image Alt Text: In your Shopify admin, ensure that each variant image has alt text that exactly matches its corresponding variant option name. Also, make sure that the the variant name is 'color'. If you have images that need to be used for all variants, please set the alt text as 'public'.

By following these steps, you can effectively display only the images of the selected variant in your product gallery. This enhancement will not only improve user experience but also elevate the overall visual appeal of your Shopify store.

For any questions or further assistance, please don't hesitate to reach out. Simply leave us a message, and we will respond to you as soon as possible. We're here to help and look forward to working with you!