Shopify themes, liquid, logos, and UX
Hi everyone,
I am experiencing an issue with the product images on my Shopify store. The main problem is that when viewing product images in larger views (zoom) on both mobile and desktop, the images overflow beyond the screen. This makes it difficult for customers to see the full image properly.
I am using Motion Theme.
Here is a sample for overflow product image.
https://mottoplan.com/collections/digital-planners/products/digital-planner-2025-rainbow
How can I fix this?
Thanks in advance!
Solved! Go to the solution
This is an accepted solution.
Hi @Erdem_2,
Please go to media.liquid file and change all code:
{% comment %}
Renders a media element for the product gallery.
Media types include: image, video, external_video and model.
Accepts:
- media: {Object} Media Liquid object (required)
- featured_media: {Object} Media Liquid object (required) - featured media of a given product or variant
- loading {String}
- sizes
- sizeVariable
- fallback
{% endcomment %}
{%- liquid
assign is_featured = false
if featured_media == media
assign is_featured = true
endif
assign has_video = false
assign video_type = ''
assign video_modal = false
assign image_set = false
assign image_set_group = ''
if media.alt contains '#'
assign image_set_full = media.alt | split: '#' | last
if image_set_full contains '_'
assign image_set = true
assign image_set_group = image_set_full | split: '_' | first
endif
endif
-%}
<div class="product-main-slide {% if is_featured %}starting-slide{% else %}secondary-slide{% endif %}"
data-index="{{ loopIndex0 }}"
{% if image_set %}
data-set-name="{{image_set_group}}"
data-group="{{image_set_full}}"
{% endif %}>
{%- liquid
case media.media_type
when 'external_video'
assign has_video = true
assign video_type = media.host
assign video_id = media.external_id
when 'video'
assign has_video = true
assign video_type = 'mp4'
endcase
if has_video and video_style == 'unmuted'
assign video_modal = true
endif
-%}
<div data-product-image-main class="product-image-main">
{%- liquid
assign media_aspect_ratio = media.aspect_ratio
assign media_width = 800
assign media_height = 800
if media.media_type != 'image'
assign media_width = media.preview_image.width
assign media_height = media.preview_image.height
endif
-%}
{%- if media.media_type == 'model' -%}
{%- liquid
if media.preview_image.aspect_ratio
assign media_aspect_ratio = media.preview_image.aspect_ratio
endif
-%}
<div
class="image-wrap" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;"
data-product-media-type-model
data-media-id="{{ section_id }}-{{ media.id }}">
{{ media | model_viewer_tag: image_size: product_zoom_size, reveal: 'interaction', toggleable: true, data-model-id: media.id }}
</div>
<button class="hide btn btn--circle btn--static product-single__close-media">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-close" viewBox="0 0 64 64"><title>icon-X</title><path d="m19 17.61 27.12 27.13m0-27.12L19 44.74"/></svg>
</button>
{%- else -%}
{%- if has_video and video_style == 'unmuted' -%}
{%- assign media_aspect_ratio = media.preview_image.aspect_ratio -%}
{%- endif -%}
<div class="image-wrap{% if has_video and video_modal == false %} hide{% endif %}" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;">
{%- capture image_classes -%}
{% if product_zoom_enable %}photoswipe__image{% endif %}
{%- endcapture -%}
{%- render 'image-element',
img: media.preview_image,
type: 'photoswipe',
classes: image_classes,
alt: media.alt | escape | split: '#' | first,
widths: '360, 540, 720, 900, 1080',
product_zoom_size: product_zoom_size,
loopIndex: loopIndex,
media: media,
media_width: media_width,
media_height: media_height,
sizes: sizes,
sizeVariable: sizeVariable,
fallback: fallback,
loading: loading,
-%}
{%- if product_zoom_enable and media.media_type == 'image' -%}
<button type="button" class="btn btn--no-animate btn--body btn--circle js-photoswipe__zoom product__photo-zoom">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-search" viewBox="0 0 64 64"><title>icon-search</title><path d="M47.16 28.58A18.58 18.58 0 1 1 28.58 10a18.58 18.58 0 0 1 18.58 18.58ZM54 54 41.94 42"/></svg>
<span class="icon__fallback-text">{{ 'general.accessibility.close_modal' | t }}</span>
</button>
{%- endif -%}
</div>
{%- if has_video and video_modal -%}
{%- if video_type == 'youtube' -%}
<a href="https://youtube.com/watch?v={{ media.external_id }}" class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'vimeo' -%}
<a href="https://player.vimeo.com/video/{{ media.external_id }}"
class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
data-video-loop="{{ video_looping }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<button type="button" class="btn btn--circle btn--large btn--static product-video-trigger product-video-trigger--mp4">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</button>
{% comment %}
Hidden video element that gets placed in the video modal
{% endcomment %}
<video
playsinline
{% if video_looping %}loop{% endif %}
controls
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
class="hide product-video-mp4-sound">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
{%- endif -%}
{%- if has_video -%}
{%- unless video_modal -%}
<div
data-video-type="{{ video_type }}"
class="product__video-wrapper{% if video_type == 'youtube' or video_type == 'vimeo' %} loading{% endif %}"
data-video-style="{{ video_style }}"
style="padding-bottom: {{ 100 | divided_by: media.aspect_ratio }}%;">
{%- if video_type == 'youtube' or video_type == 'vimeo' -%}
<div
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
data-video-loop="{{ video_looping }}"
data-video-id="{{ video_id }}"
>
</div>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<video
playsinline
{% if video_looping %}loop{% endif %}
{% if video_style == 'muted' %}muted{% endif %}
{% if video_style == 'unmuted' %}controls{% endif %}
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
</div>
{%- endunless -%}
{%- endif -%}
{%- endif -%}
</div>
</div>
I can help fix the image overflow issue in the Motion theme by adjusting the CSS. Let me guide you!
Hi @Erdem_2,
Please send me a screenshot of the error description, I will check it again, because now I checked and everything works fine
Hi @namphan ,
I attached 2 pictures for 2 different products. They are zoomed pictures.
1. Product picture is 800x800 px ( quality is low but fits the screen )
2. Product picture is 2130 x 2130 px ( quality is good but when it is zoomed it overflows ).
Because of the quality issue I need to use 2130 x 2130 px and want them not to overflow.
Thanks for your interest and help.
Hi @Erdem_2,
Please send me the code of product-images.liquid file, I will check it
Hi @namphan ,
Here it is.
{% comment %}
Parameters
context - used to determine whether on the featured product or main product template
sizes
sizeVariable
fallback
{% endcomment %}
{%- liquid
# Product images and thumbnails on the main product template should load early
if context == 'main-product'
assign loading = 'eager'
endif
-%}
{%- assign featured_media = product.selected_or_first_available_variant.featured_media | default: product.featured_media -%}
{%- unless product.empty? -%}
<div
data-product-images
data-zoom="{{ product_zoom_enable }}"
data-has-slideshow="{% if product.media.size > 1 %}true{% else %}false{% endif %}">
<div class="product__photos product__photos-{{ section_id }} product__photos--{{ thumbnail_position }}">
<div class="product__main-photos" data-aos data-product-single-media-group>
<div
data-product-photos
data-zoom="{{ product_zoom_enable }}"
class="product-slideshow"
id="ProductPhotos-{{ section_id }}"
>
{%- for media in product.media -%}
{%- render 'media',
section_id: section_id,
media: media,
featured_media: featured_media,
loopIndex0: forloop.index0,
loopIndex: forloop.index,
product_zoom_enable: product_zoom_enable,
product_zoom_size: product_zoom_size,
product_image_size: product_image_size,
isModal: isModal,
video_looping: video_looping,
video_style: video_style,
sizes: sizes,
sizeVariable: sizeVariable,
fallback: fallback,
loading: loading,
-%}
{%- endfor -%}
</div>
{%- assign first_3d_model = product.media | where: 'media_type', 'model' | first -%}
{%- if first_3d_model -%}
<button
aria-label="{{ 'products.product.view_in_space_label' | t }}"
class="product-single__view-in-space"
data-shopify-xr
data-shopify-model3d-id="{{ first_3d_model.id }}"
data-shopify-title="{{ product.title }}"
data-shopify-xr-hidden
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-3d" viewBox="18.24 17.35 24.52 28.3"><path fill="#3A3A3A" d="m30.5 17.35-12.26 7.07v14.16l12.26 7.07 12.26-7.08V24.42L30.5 17.35zM20.24 37.42V25.58l10.26-5.93 10.13 5.85-10.13 5.88v12l-10.26-5.96z"/></svg>
<span class='product-single__view-in-space-text'>
{{ 'products.product.view_in_space' | t }}
</span>
</button>
{%- endif -%}
<div class="product__photo-dots product__photo-dots--{{ section_id }}"></div>
</div>
<div
data-product-thumbs
class="product__thumbs product__thumbs--{{ thumbnail_position }}{% if product.media.size == 1 %} hide{% endif %}"
data-position="{{ thumbnail_position }}"
data-aos>
{%- if thumbnail_arrows -%}
<button type="button" class="product__thumb-arrow product__thumb-arrow--prev hide">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-chevron-left" viewBox="0 0 284.49 498.98"><title>icon-chevron-left</title><path d="M249.49 0a35 35 0 0 1 24.75 59.75L84.49 249.49l189.75 189.74a35.002 35.002 0 1 1-49.5 49.5L10.25 274.24a35 35 0 0 1 0-49.5L224.74 10.25A34.89 34.89 0 0 1 249.49 0Z"/></svg>
</button>
{%- endif -%}
<div class="product__thumbs--scroller">
{%- if product.media.size > 1 -%}
{%- for media in product.media -%}
{%- liquid
assign image_set = false
assign image_set_group = ''
if media.alt contains '#'
assign image_set_full = media.alt | split: '#' | last
if image_set_full contains '_'
assign image_set = true
assign image_set_group = image_set_full | split: '_' | first
endif
endif
-%}
<div class="product__thumb-item"
data-index="{{ forloop.index0 }}"
{% if image_set %}
data-set-name="{{image_set_group}}"
data-group="{{image_set_full}}"
{% endif %}>
<a
href="{{ media.preview_image | img_url: product_zoom_size }}"
data-product-thumb
class="product__thumb js-no-transition"
data-index="{{ forloop.index0 }}"
data-id="{{ media.id }}">
<div class="image-wrap image-wrap__thumbnail" style="height: 0; padding-bottom: {{ 100 | divided_by: media.preview_image.aspect_ratio }}%;">
{%- if media.media_type == 'video' or media.media_type == 'external_video' -%}
<span class="product__thumb-icon">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</span>
{%- endif -%}
{%- if media.media_type == 'model' -%}
<span class="product__thumb-icon">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-3d" viewBox="18.24 17.35 24.52 28.3"><path fill="#3A3A3A" d="m30.5 17.35-12.26 7.07v14.16l12.26 7.07 12.26-7.08V24.42L30.5 17.35zM20.24 37.42V25.58l10.26-5.93 10.13 5.85-10.13 5.88v12l-10.26-5.96z"/></svg>
</span>
{%- endif -%}
{%- capture image_classes -%}
appear-delay-{{ forloop.index | times: 3 }}
{%- endcapture -%}
{%- render 'image-element',
img: media.preview_image,
alt: media.alt | escape | split: '#' | first,
widths: '100, 360, 540',
classes: image_classes,
sizeVariable: '80px',
loading: loading,
-%}
</div>
</a>
</div>
{%- endfor -%}
{%- endif -%}
</div>
{%- if thumbnail_arrows -%}
<button type="button" class="product__thumb-arrow product__thumb-arrow--next">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-chevron-right" viewBox="0 0 284.49 498.98"><title>icon-chevron</title><path d="M35 498.98a35 35 0 0 1-24.75-59.75l189.74-189.74L10.25 59.75a35.002 35.002 0 0 1 49.5-49.5l214.49 214.49a35 35 0 0 1 0 49.5L59.75 488.73A34.89 34.89 0 0 1 35 498.98Z"/></svg>
</button>
{%- endif -%}
</div>
</div>
</div>
{% if thumbnail_height == 'fixed' %}
{% style %}
.product__photos-{{ section_id }} .product__thumbs:not(.product__thumbs--below) {
min-height: 400px;
max-height: 400px;
}
@media screen and (max-width: 798px) {
.product__photos-{{ section_id }} .product__thumbs:not(.product__thumbs--below) {
min-height: 300px;
max-height: 300px;
}
}
{% endstyle %}
{% endif %}
<script type="application/json" id="ModelJson-{{ section_id }}">
{{ product.media | where: 'media_type', 'model' | json }}
</script>
{%- else -%}
<div class="product__photos">
<div class="product__main-photos" style="width: 100%">
<div data-product-photos>
<div class="product-main-slide" data-index="{{ forloop.index0 }}">
<a href="#">
{{ 'product-1' | placeholder_svg_tag: 'placeholder-svg' }}
</a>
</div>
</div>
</div>
</div>
{%- endunless -%}
Hi @Erdem_2,
Please send me the code of media.liquid file, the code to change here and I will check it
Hi @namphan ,
Here the media.liquid.file .
{% comment %}
Renders a media element for the product gallery.
Media types include: image, video, external_video and model.
Accepts:
- media: {Object} Media Liquid object (required)
- featured_media: {Object} Media Liquid object (required) - featured media of a given product or variant
- loading {String}
- sizes
- sizeVariable
- fallback
{% endcomment %}
{%- liquid
assign is_featured = false
if featured_media == media
assign is_featured = true
endif
assign has_video = false
assign video_type = ''
assign video_modal = false
assign image_set = false
assign image_set_group = ''
if media.alt contains '#'
assign image_set_full = media.alt | split: '#' | last
if image_set_full contains '_'
assign image_set = true
assign image_set_group = image_set_full | split: '_' | first
endif
endif
-%}
<div class="product-main-slide {% if is_featured %}starting-slide{% else %}secondary-slide{% endif %}"
data-index="{{ loopIndex0 }}"
{% if image_set %}
data-set-name="{{image_set_group}}"
data-group="{{image_set_full}}"
{% endif %}>
{%- liquid
case media.media_type
when 'external_video'
assign has_video = true
assign video_type = media.host
assign video_id = media.external_id
when 'video'
assign has_video = true
assign video_type = 'mp4'
endcase
if has_video and video_style == 'unmuted'
assign video_modal = true
endif
-%}
<div data-product-image-main class="product-image-main">
{%- liquid
assign media_aspect_ratio = media.aspect_ratio
assign media_width = media.width
assign media_height = media.height
if media.media_type != 'image'
assign media_width = media.preview_image.width
assign media_height = media.preview_image.height
endif
-%}
{%- if media.media_type == 'model' -%}
{%- liquid
if media.preview_image.aspect_ratio
assign media_aspect_ratio = media.preview_image.aspect_ratio
endif
-%}
<div
class="image-wrap" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;"
data-product-media-type-model
data-media-id="{{ section_id }}-{{ media.id }}">
{{ media | model_viewer_tag: image_size: product_zoom_size, reveal: 'interaction', toggleable: true, data-model-id: media.id }}
</div>
<button class="hide btn btn--circle btn--static product-single__close-media">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-close" viewBox="0 0 64 64"><title>icon-X</title><path d="m19 17.61 27.12 27.13m0-27.12L19 44.74"/></svg>
</button>
{%- else -%}
{%- if has_video and video_style == 'unmuted' -%}
{%- assign media_aspect_ratio = media.preview_image.aspect_ratio -%}
{%- endif -%}
<div class="image-wrap{% if has_video and video_modal == false %} hide{% endif %}" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;">
{%- capture image_classes -%}
{% if product_zoom_enable %}photoswipe__image{% endif %}
{%- endcapture -%}
{%- render 'image-element',
img: media.preview_image,
type: 'photoswipe',
classes: image_classes,
alt: media.alt | escape | split: '#' | first,
widths: '360, 540, 720, 900, 1080',
product_zoom_size: product_zoom_size,
loopIndex: loopIndex,
media: media,
media_width: media_width,
media_height: media_height,
sizes: sizes,
sizeVariable: sizeVariable,
fallback: fallback,
loading: loading,
-%}
{%- if product_zoom_enable and media.media_type == 'image' -%}
<button type="button" class="btn btn--no-animate btn--body btn--circle js-photoswipe__zoom product__photo-zoom">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-search" viewBox="0 0 64 64"><title>icon-search</title><path d="M47.16 28.58A18.58 18.58 0 1 1 28.58 10a18.58 18.58 0 0 1 18.58 18.58ZM54 54 41.94 42"/></svg>
<span class="icon__fallback-text">{{ 'general.accessibility.close_modal' | t }}</span>
</button>
{%- endif -%}
</div>
{%- if has_video and video_modal -%}
{%- if video_type == 'youtube' -%}
<a href="https://youtube.com/watch?v={{ media.external_id }}" class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'vimeo' -%}
<a href="https://player.vimeo.com/video/{{ media.external_id }}"
class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
data-video-loop="{{ video_looping }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<button type="button" class="btn btn--circle btn--large btn--static product-video-trigger product-video-trigger--mp4">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</button>
{% comment %}
Hidden video element that gets placed in the video modal
{% endcomment %}
<video
playsinline
{% if video_looping %}loop{% endif %}
controls
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
class="hide product-video-mp4-sound">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
{%- endif -%}
{%- if has_video -%}
{%- unless video_modal -%}
<div
data-video-type="{{ video_type }}"
class="product__video-wrapper{% if video_type == 'youtube' or video_type == 'vimeo' %} loading{% endif %}"
data-video-style="{{ video_style }}"
style="padding-bottom: {{ 100 | divided_by: media.aspect_ratio }}%;">
{%- if video_type == 'youtube' or video_type == 'vimeo' -%}
<div
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
data-video-loop="{{ video_looping }}"
data-video-id="{{ video_id }}"
>
</div>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<video
playsinline
{% if video_looping %}loop{% endif %}
{% if video_style == 'muted' %}muted{% endif %}
{% if video_style == 'unmuted' %}controls{% endif %}
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
</div>
{%- endunless -%}
{%- endif -%}
{%- endif -%}
</div>
</div>
This is an accepted solution.
Hi @Erdem_2,
Please go to media.liquid file and change all code:
{% comment %}
Renders a media element for the product gallery.
Media types include: image, video, external_video and model.
Accepts:
- media: {Object} Media Liquid object (required)
- featured_media: {Object} Media Liquid object (required) - featured media of a given product or variant
- loading {String}
- sizes
- sizeVariable
- fallback
{% endcomment %}
{%- liquid
assign is_featured = false
if featured_media == media
assign is_featured = true
endif
assign has_video = false
assign video_type = ''
assign video_modal = false
assign image_set = false
assign image_set_group = ''
if media.alt contains '#'
assign image_set_full = media.alt | split: '#' | last
if image_set_full contains '_'
assign image_set = true
assign image_set_group = image_set_full | split: '_' | first
endif
endif
-%}
<div class="product-main-slide {% if is_featured %}starting-slide{% else %}secondary-slide{% endif %}"
data-index="{{ loopIndex0 }}"
{% if image_set %}
data-set-name="{{image_set_group}}"
data-group="{{image_set_full}}"
{% endif %}>
{%- liquid
case media.media_type
when 'external_video'
assign has_video = true
assign video_type = media.host
assign video_id = media.external_id
when 'video'
assign has_video = true
assign video_type = 'mp4'
endcase
if has_video and video_style == 'unmuted'
assign video_modal = true
endif
-%}
<div data-product-image-main class="product-image-main">
{%- liquid
assign media_aspect_ratio = media.aspect_ratio
assign media_width = 800
assign media_height = 800
if media.media_type != 'image'
assign media_width = media.preview_image.width
assign media_height = media.preview_image.height
endif
-%}
{%- if media.media_type == 'model' -%}
{%- liquid
if media.preview_image.aspect_ratio
assign media_aspect_ratio = media.preview_image.aspect_ratio
endif
-%}
<div
class="image-wrap" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;"
data-product-media-type-model
data-media-id="{{ section_id }}-{{ media.id }}">
{{ media | model_viewer_tag: image_size: product_zoom_size, reveal: 'interaction', toggleable: true, data-model-id: media.id }}
</div>
<button class="hide btn btn--circle btn--static product-single__close-media">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-close" viewBox="0 0 64 64"><title>icon-X</title><path d="m19 17.61 27.12 27.13m0-27.12L19 44.74"/></svg>
</button>
{%- else -%}
{%- if has_video and video_style == 'unmuted' -%}
{%- assign media_aspect_ratio = media.preview_image.aspect_ratio -%}
{%- endif -%}
<div class="image-wrap{% if has_video and video_modal == false %} hide{% endif %}" style="height: 0; padding-bottom: {{ 100 | divided_by: media_aspect_ratio }}%;">
{%- capture image_classes -%}
{% if product_zoom_enable %}photoswipe__image{% endif %}
{%- endcapture -%}
{%- render 'image-element',
img: media.preview_image,
type: 'photoswipe',
classes: image_classes,
alt: media.alt | escape | split: '#' | first,
widths: '360, 540, 720, 900, 1080',
product_zoom_size: product_zoom_size,
loopIndex: loopIndex,
media: media,
media_width: media_width,
media_height: media_height,
sizes: sizes,
sizeVariable: sizeVariable,
fallback: fallback,
loading: loading,
-%}
{%- if product_zoom_enable and media.media_type == 'image' -%}
<button type="button" class="btn btn--no-animate btn--body btn--circle js-photoswipe__zoom product__photo-zoom">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-search" viewBox="0 0 64 64"><title>icon-search</title><path d="M47.16 28.58A18.58 18.58 0 1 1 28.58 10a18.58 18.58 0 0 1 18.58 18.58ZM54 54 41.94 42"/></svg>
<span class="icon__fallback-text">{{ 'general.accessibility.close_modal' | t }}</span>
</button>
{%- endif -%}
</div>
{%- if has_video and video_modal -%}
{%- if video_type == 'youtube' -%}
<a href="https://youtube.com/watch?v={{ media.external_id }}" class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'vimeo' -%}
<a href="https://player.vimeo.com/video/{{ media.external_id }}"
class="btn btn--circle btn--large btn--static product-video-trigger"
data-video-id="{{ media.external_id }}"
data-video-loop="{{ video_looping }}"
>
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</a>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<button type="button" class="btn btn--circle btn--large btn--static product-video-trigger product-video-trigger--mp4">
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-play" viewBox="18.24 17.35 24.52 28.3"><path fill="#323232" d="M22.1 19.151v25.5l20.4-13.489-20.4-12.011z"/></svg>
</button>
{% comment %}
Hidden video element that gets placed in the video modal
{% endcomment %}
<video
playsinline
{% if video_looping %}loop{% endif %}
controls
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
class="hide product-video-mp4-sound">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
{%- endif -%}
{%- if has_video -%}
{%- unless video_modal -%}
<div
data-video-type="{{ video_type }}"
class="product__video-wrapper{% if video_type == 'youtube' or video_type == 'vimeo' %} loading{% endif %}"
data-video-style="{{ video_style }}"
style="padding-bottom: {{ 100 | divided_by: media.aspect_ratio }}%;">
{%- if video_type == 'youtube' or video_type == 'vimeo' -%}
<div
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
data-video-loop="{{ video_looping }}"
data-video-id="{{ video_id }}"
>
</div>
{%- endif -%}
{%- if video_type == 'mp4' -%}
<video
playsinline
{% if video_looping %}loop{% endif %}
{% if video_style == 'muted' %}muted{% endif %}
{% if video_style == 'unmuted' %}controls{% endif %}
controlsList="nodownload"
poster="{{ media.preview_image | img_url: product_image_size }}"
data-image-count="{{ product.media.size }}"
data-video-type="{{ video_type }}"
data-video-style="{{ video_style }}"
id="ProductVideo-{{ section_id }}-{{ loopIndex }}"
class="product__video">
{%- for source in media.sources -%}
<source src="{{ source.url }}" type="{{ source.mime_type }}">
{%- endfor -%}
Your browser does not support the video tag.
</video>
{%- endif -%}
</div>
{%- endunless -%}
{%- endif -%}
{%- endif -%}
</div>
</div>
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