Shopify themes, liquid, logos, and UX
Hello, i modified my code so i can move product images with arrow keys, its working fine, i can move with arrow key, click it manually, and the thumbnail highlight is also following the arrow keys.
But the problem is, after i pick the variant, the preview image is show two images, and it fix the issue if i click the thumbnail manually.
Please help, this is the website
And this is the code for product gallery: https://n9layg256hgz8hfx-886341698.shopifypreview.com
<script type="application/pxs-animation-mapping+json">
{
"blocks": [
".product-gallery--viewport",
".product-gallery--navigation"
],
"elements": [
".product-gallery--media",
".product-gallery--media-thumbnail"
]
}
</script>
{% assign selected_variant = product.selected_or_first_available_variant %}
{% assign selected_media = selected_variant.featured_media | default: product.featured_media %}
<div
class="product-gallery {{ class }}"
data-product-gallery
data-product-gallery-layout="{{ layout }}"
{{ block.shopify_attributes }}
>
<div
class="product-gallery--viewport"
data-product-gallery-viewport
>
{% for media in product.media %}
<figure
class="
product-gallery--media
product-gallery--{{ media.media_type }}
{%- if forloop.first -%}loaded-first{%- endif -%}
"
tabindex="-1"
data-product-gallery-figure="{{ forloop.index0 }}"
data-product-gallery-selected="{%- if forloop.first -%}true{%- else -%}false{%- endif -%}"
data-media="{{ media.id }}"
data-media-type="{{ media.media_type }}"
{% unless forloop.first %}
hidden
{% endunless %}
>
{% case media.media_type %}
{% when 'image' %}
{% assign scale = 1 %}
{% if enable_zoom %}
{% assign scale = 1.5 %}
{% endif %}
{%
render 'rimg',
img: media,
size: 'x700',
scale: scale,
lazy: true
%}
{% when 'external_video' %}
{{ media | media_tag: image_size: '1024x' }}
{% when 'model' %}
{{ media | model_viewer_tag: image_size: '1024x', reveal: 'interaction' , toggleable: true, interaction-prompt-threshold: 0 }}
<noscript>
<img
src="{{ media.preview_image | img_url: '1024x' }}"
alt="{{ media.preview_image.alt | escape }}"
width="{{ media.preview_image.width }}"
height="{{ media.preview_image.height }}"
loading="lazy"
>
</noscript>
{% when 'video' %}
{{ media | media_tag: image_size: '1024x' }}
{% else %}
{{ media | media_tag }}
{% endcase %}
</figure>
{% else %}
<figure
class="
product-gallery--media
product-gallery--image
product-gallery--image-placeholder
"
>
{% if onboarding %}
{{ 'product-1' | placeholder_svg_tag: 'placeholder-svg' }}
{% else %}
{{ 'image' | placeholder_svg_tag: 'placeholder-svg' }}
{% endif %}
</figure>
{% endfor %}
{% assign first_model = product.media | where: "media_type", "model" | first %}
{% if selected_media.media_type == 'model' %}
{% assign model = selected_media %}
{% else %}
{% assign model = first_model %}
{% endif %}
{% if model %}
<script>
window.ShopifyXR=window.ShopifyXR||function(){(ShopifyXR.q=ShopifyXR.q||[]).push(arguments)}
{% assign models = product.media | where: 'media_type', 'model' | json %}
ShopifyXR('addModels', {{ models }});
</script>
<button
class="product-gallery--viewinyourspace"
data-default-model-id="{{ first_model.id }}"
data-shopify-xr
data-shopify-model3d-id="{{ model.id }}"
data-shopify-title="{{ product.title }}"
data-shopify-xr-hidden
>
{% render 'icon-library', id: 'icon-3D' %}
{{ 'product.media.view_in_your_space' | t }}
</button>
{% endif %}
</div>
{% if product.media.size > 1 %}
<div
class="product-gallery--navigation"
data-product-gallery-navigation
>
{% for media in product.media %}
<button
class="
product-gallery--media-thumbnail
product-gallery--{{ media.media_type }}-thumbnail
"
type="button"
tab-index="0"
aria-label="{{ media.alt }} {{ 'general.accessibility.nav_product_thumbnail' | t }}"
data-product-gallery-thumbnail="{{ forloop.index0 }}"
data-product-gallery-selected="{%- if forloop.first -%}true{%- else -%}false{%- endif -%}"
data-media="{{ media.id }}"
data-media-type="{{ media.media_type }}"
>
{% if media.media_type == 'video' or media.media_type == 'external_video' %}
{% render 'icon-library', id: 'icon-play-thumb' %}
{% elsif media.media_type == 'model' %}
{% render 'icon-library', id: 'icon-model-thumb' %}
{% endif %}
{%
render 'rimg',
class: 'product-gallery--media-thumbnail-img',
img: media.preview_image,
size: '100x',
crop: 'center',
lazy: true,
%}
</button>
{% endfor %}
</div>
{% endif %}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const gallery = document.querySelector('[data-product-gallery]');
if (!gallery) {
console.error('Gallery element not found');
return;
}
const figures = gallery.querySelectorAll('[data-product-gallery-figure]');
const thumbnails = gallery.querySelectorAll('[data-product-gallery-thumbnail]');
let currentIndex = Array.from(figures).findIndex(figure => figure.dataset.productGallerySelected === 'true');
function updateGallery(index) {
figures.forEach((figure, i) => {
if (i === index) {
figure.removeAttribute('hidden');
figure.dataset.productGallerySelected = 'true';
} else {
figure.setAttribute('hidden', 'hidden');
figure.dataset.productGallerySelected = 'false';
}
});
thumbnails.forEach((thumbnail, i) => {
thumbnail.dataset.productGallerySelected = i === index ? 'true' : 'false';
});
currentIndex = index;
}
// Ensure only one image is selected on load
updateGallery(currentIndex);
document.addEventListener('keydown', function(event) {
if (event.key === 'ArrowRight') {
updateGallery((currentIndex + 1) % figures.length);
} else if (event.key === 'ArrowLeft') {
updateGallery((currentIndex - 1 + figures.length) % figures.length);
}
});
thumbnails.forEach((thumbnail, index) => {
thumbnail.addEventListener('click', function() {
updateGallery(index);
});
});
// Handle variant change
document.addEventListener('variant:change', function(event) {
const newVariant = event.detail.variant;
const newMediaId = newVariant.featured_media ? newVariant.featured_media.id : null;
if (newMediaId) {
const newIndex = Array.from(figures).findIndex(figure => figure.dataset.media == newMediaId);
if (newIndex !== -1) {
updateGallery(newIndex);
}
} else {
console.warn('No media associated with the selected variant.');
}
});
});
</script>
Learn how to build powerful custom workflows in Shopify Flow with expert guidance from ...
By Jacqui May 7, 2025Did You Know? May is named after Maia, the Roman goddess of growth and flourishing! ...
By JasonH May 2, 2025Discover opportunities to improve SEO with new guidance available from Shopify’s growth...
By Jacqui May 1, 2025