Skip to content

Instantly share code, notes, and snippets.

@dpw1
Created January 5, 2026 09:41
Show Gist options
  • Select an option

  • Save dpw1/6eea05b0b49ab23a9a559a57861d706c to your computer and use it in GitHub Desktop.

Select an option

Save dpw1/6eea05b0b49ab23a9a559a57861d706c to your computer and use it in GitHub Desktop.
<style>
@media screen and (min-width: 750px) {
.product--thumbnail .product__media-list, .product--thumbnail_slider .product__media-list {
padding-bottom: 0 !important;
padding: 0;
margin: 0;
gap: 0;
}
}
{% assign button_height = 30 %}
[id*='MediaGallery'] {
display: flex;
flex-direction: row;
gap: {{ section.settings.desktop_gap }}px;
align-items: flex-start;
margin-bottom: {{ section.settings.desktop_margin_bottom }}px;
}
.thumbnail-slider .slider-button{
display: none;
}
.thumbnail-scroll-button {
position: absolute;
left: 0;
width: 100%;
height: {{ button_height }}px;
background: {{ section.settings.arrow_bg_color }};
border: none;
cursor: pointer;
z-index: 1;
display: none;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease-in-out;
{% unless section.settings.show_arrows_desktop %}
display: none;
{% endunless %}
}
{% if section.settings.show_arrows_on_hover %}
[id*='GalleryThumbnails']:not(:hover) .thumbnail-scroll-button {
opacity: 0;
}
{% endif %}
.thumbnail-scroll-button:hover {
opacity: {{ section.settings.arrow_hover_opacity | divided_by: 100.0 }};
}
{% if section.settings.display_arrow_above_desktop %}
[id*="GalleryThumbnails"] ul{
}
{% endif %}
.thumbnail-scroll-button.top {
top: 0;
}
.thumbnail-scroll-button.bottom {
bottom: 0;
}
.thumbnail-scroll-button svg {
width: 16px;
height: 16px;
pointer-events: none;
transform: rotate(180deg);
}
.thumbnail-scroll-button.bottom svg {
transform: rotate(0deg);
}
[id*='GalleryThumbnails'] {
width: 100px;
order: -1;
height: 100%;
position: relative;
{% unless section.settings.show_desktop %}
display: none;
{% endunless %}
{% if section.settings.hide_scrollbar %}
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 10+ */
{% endif %}
}
{% if section.settings.hide_scrollbar %}
[id*='GalleryThumbnails'] {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 10+ */
}
[id*='GalleryThumbnails'] ::-webkit-scrollbar {
display: none; /* Safari and Chrome */
}
{% endif %}
[id*='GalleryThumbnails'] .slider-component {
height: 100%;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
/* Hide scrollbar when setting is enabled */
[id*='GalleryThumbnails'] .slider-component.hide-scrollbar {
scrollbar-width: none;
}
[id*='GalleryThumbnails'] .slider-component.hide-scrollbar::-webkit-scrollbar {
display: none;
}
/* Webkit scrollbar styles */
[id*='GalleryThumbnails'] .slider-component::-webkit-scrollbar {
width: 4px;
}
[id*='GalleryThumbnails'] .slider-component::-webkit-scrollbar-track {
background: transparent;
}
[id*='GalleryThumbnails'] .slider-component::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 2px;
}
[id*='GalleryThumbnails'] .thumbnail-list {
display: flex;
flex-direction: column;
gap: 10px;
height: auto;
min-height: 100%;
overflow-y: scroll;
overflow-y: scroll;
height: 100%;
flex-wrap: nowrap;
}
.thumbnail-list__item {
width: 100%;
{% if section.settings.thumbnail_aspect_desktop == 'original' %}
display: flex;
align-items: center;
justify-content: center;
{% endif %}
}
[id*='GalleryThumbnails'] .thumbnail {
width: 100%;
{% if section.settings.thumbnail_aspect_desktop == 'square' %}
aspect-ratio: 1;
object-fit: cover;
{% else %}
height: auto;
object-fit: contain;
position: relative;
{% endif %}
}
{% if section.settings.thumbnail_aspect_desktop == 'original' %}
.thumbnail.global-media-settings img {
border-radius: 0;
border-bottom: unset !important;
}
[id] .thumbnail[aria-current]{
box-shadow: unset !important;
border: unset !important;
}
[id] .thumbnail[aria-current] > img{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border: {{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% endif %}
{% if section.settings.thumbnail_aspect_desktop == 'square' %}
[id] .thumbnail[aria-current]{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% endif %}
[id*='GalleryViewer'] {
flex: 1;
width: {% if section.settings.show_desktop %}calc(100% - 120px){% else %}100%{% endif %};
}
@media screen and (max-width: 749px) {
[id*='MediaGallery'] {
flex-direction: column;
gap: {{ section.settings.mobile_gap }}px;
margin-bottom: {{ section.settings.mobile_margin_bottom }}px;
}
[id*='GalleryThumbnails'] {
width: 100%;
order: 0;
height: auto !important;
overflow: visible;
{% unless section.settings.show_mobile %}
display: none;
{% endunless %}
}
[id*='GalleryThumbnails'] .slider-component {
height: auto !important;
overflow: visible;
}
[id*='GalleryThumbnails'] .thumbnail-list {
{% if section.settings.show_mobile %}
flex-direction: column;
overflow-y: auto;
max-height: 300px;
{% else %}
flex-direction: row;
overflow-x: auto;
{% endif %}
padding-bottom: 10px;
}
[id*='GalleryThumbnails'] .thumbnail {
{% if section.settings.show_mobile %}
width: 100%;
{% if section.settings.thumbnail_aspect_mobile == 'square' %}
aspect-ratio: 1;
{% else %}
height: auto;
{% endif %}
{% else %}
width: 80px;
flex-shrink: 0;
{% if section.settings.thumbnail_aspect_mobile == 'square' %}
height: 80px;
{% else %}
height: auto;
max-height: 80px;
{% endif %}
{% endif %}
}
{% if section.settings.thumbnail_aspect_mobile == 'square' %}
[id] .thumbnail[aria-current] img {
box-shadow: unset !important;
border: unset !important;
}
[id] .thumbnail[aria-current] {
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }} !important;
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }} !important;
}
{% endif %}
[id*='GalleryViewer'] {
width: 100%;
}
.thumbnail-scroll-button {
{% unless section.settings.show_arrows_mobile %}
display: none;
{% endunless %}
}
{% if section.settings.display_arrow_above_mobile %}
[id*="GalleryThumbnails"] ul{
padding: 0 !important;
padding-top: 5px !important;
}
{% endif %}
}
@media (min-width: 750px){
{% if section.settings.thumbnail_aspect_desktop == 'square' %}
[id] .thumbnail[aria-current]{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% elsif section.settings.thumbnail_aspect_desktop == 'original' %}
[id] .thumbnail[aria-current] img{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% endif %}
}
@media screen and (max-width: 749px) {
{% if section.settings.thumbnail_aspect_mobile == 'square' %}
[id] .thumbnail[aria-current]{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% elsif section.settings.thumbnail_aspect_mobile == 'original' %}
[id] .thumbnail[aria-current] img{
box-shadow: 0 0 0 {{ section.settings.border_width }}px {{ section.settings.border_color }};
border:{{ section.settings.border_width }}px solid {{ section.settings.border_color }};
}
{% endif %}
[id*='MediaGallery'] {
flex-direction: row-reverse;
gap: unset !important;
width: 100%;
max-width: 100%;
align-items: unset !important;
justify-content: space-around;
margin-bottom: {{ section.settings.mobile_margin_bottom }}px;
}
[id*="GalleryViewer"]{
width: 100%;
max-width: 80% !important;
padding-left: 6px;
}
.product__media-item{
width: 100% !important;
}
[id*='GalleryThumbnails'] {
max-width: 20% !important;
width: 100% !important;
order: 0;
height: auto !important;
overflow: hidden;
}
[id*='GalleryThumbnails'] li{
width: 100% !important;
}
.thumbnail-slider .thumbnail-list.slider {
}
.product-media-container{
margin: 0 !important;
width: 100% !important;
max-width: 100% !important;
}
.product-media-container img{
object-fit: contain;
}
.product__media-wrapper slider-component:not(.thumbnail-slider--no-slide) {
margin-left: 0 !important;
margin-right: 0 !important;
}
.grid--peek.slider .grid__item:first-of-type {
margin-left: 0 !important;
}
.slider.slider--mobile .slider__slide{
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.slider.slider--mobile {
margin-bottom: 0 !important;
}
}
</style>
<script>
window.ezfyVerticalThumbnails = window.ezfyVerticalThumbnails || {};
ezfyVerticalThumbnails = (function () {
const ENABLE_CONSOLE_LOG = true;
function log(...args) {
if (ENABLE_CONSOLE_LOG) {
console.log(...args);
}
}
function createScrollButton(direction) {
const button = document.createElement('button');
button.className = `thumbnail-scroll-button ${direction}`;
button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4.24 6.2a.75.75 0 0 1 1.06.04l2.7 2.908 2.7-2.908a.75.75 0 0 1 1.1 1.02l-3.25 3.5a.75.75 0 0 1-1.1 0l-3.25-3.5a.75.75 0 0 1 .04-1.06"></path></svg>`;
return button;
}
function watchThumbnailSelection() {
const galleryThumbnails = document.querySelector('[id*="GalleryThumbnails"]');
if (!galleryThumbnails) return;
// Create a MutationObserver to watch for changes to aria-current
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'aria-current') {
const thumbnail = mutation.target;
if (thumbnail.getAttribute('aria-current') === 'true') {
// Scroll the thumbnail into view with smooth behavior
thumbnail.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
});
});
// Start observing all thumbnails
const thumbnails = galleryThumbnails.querySelectorAll('.thumbnail');
thumbnails.forEach(thumbnail => {
observer.observe(thumbnail, {
attributes: true,
attributeFilter: ['aria-current']
});
});
}
function addScrollButtons() {
const galleryThumbnails = document.querySelector('[id*="GalleryThumbnails"]');
if (!galleryThumbnails) return;
// Remove existing buttons if any
const existingButtons = galleryThumbnails.querySelectorAll('.thumbnail-scroll-button');
existingButtons.forEach(button => button.remove());
// Add new buttons
const topButton = createScrollButton('top');
const bottomButton = createScrollButton('bottom');
galleryThumbnails.appendChild(topButton);
galleryThumbnails.appendChild(bottomButton);
// Get the arrow behavior setting
const arrowBehavior = {{ section.settings.arrow_behavior | json }};
// Function to check scroll position and update button visibility
function updateButtonVisibility() {
const thumbnailList = galleryThumbnails.querySelector('.thumbnail-list');
if (!thumbnailList) return;
const isAtBottom = Math.abs(
(thumbnailList.scrollHeight - thumbnailList.scrollTop) - thumbnailList.clientHeight
) < 1;
const isAtTop = thumbnailList.scrollTop < 1;
// Update bottom button visibility with fade
if (isAtBottom) {
bottomButton.style.opacity = '0';
// Wait for fade out animation to complete before hiding
setTimeout(() => {
if (bottomButton.style.opacity === '0') {
bottomButton.style.display = 'none';
}
}, 300);
} else {
// First set display, then wait a frame before starting fade in
if (getComputedStyle(bottomButton).display === 'none') {
bottomButton.style.display = 'flex';
bottomButton.style.opacity = '0';
requestAnimationFrame(() => {
bottomButton.style.opacity = '{{ section.settings.arrow_default_opacity | divided_by: 100.0 }}';
});
}
}
// Update top button visibility with fade
if (isAtTop) {
topButton.style.opacity = '0';
// Wait for fade out animation to complete before hiding
setTimeout(() => {
if (topButton.style.opacity === '0') {
topButton.style.display = 'none';
}
}, 300);
} else {
// First set display, then wait a frame before starting fade in
if (getComputedStyle(topButton).display === 'none') {
topButton.style.display = 'flex';
topButton.style.opacity = '0';
requestAnimationFrame(() => {
topButton.style.opacity = '{{ section.settings.arrow_default_opacity | divided_by: 100.0 }}';
});
}
}
}
// Add scroll event listener to update button visibility
const thumbnailList = galleryThumbnails.querySelector('.thumbnail-list');
if (thumbnailList) {
thumbnailList.addEventListener('scroll', updateButtonVisibility);
// Initial check with a slight delay to ensure proper calculation
setTimeout(updateButtonVisibility, 100);
}
// Add click handlers
topButton.addEventListener('click', () => {
if (arrowBehavior === 'navigate') {
const currentThumbnail = galleryThumbnails.querySelector('.thumbnail[aria-current="true"]');
if (!currentThumbnail) return;
const allThumbnails = galleryThumbnails.querySelectorAll('.thumbnail');
const currentIndex = Array.from(allThumbnails).indexOf(currentThumbnail);
// Find previous thumbnail or wrap to last
const prevThumbnail = currentIndex > 0
? allThumbnails[currentIndex - 1]
: allThumbnails[allThumbnails.length - 1];
prevThumbnail.click();
prevThumbnail.scrollIntoView({ behavior: 'smooth', block: 'center' });
} else {
// Scroll only mode
const thumbnailList = galleryThumbnails.querySelector('.thumbnail-list');
if (thumbnailList) {
thumbnailList.scrollBy({ top: -100, behavior: 'smooth' });
}
}
});
bottomButton.addEventListener('click', () => {
if (arrowBehavior === 'navigate') {
const currentThumbnail = galleryThumbnails.querySelector('.thumbnail[aria-current="true"]');
if (!currentThumbnail) return;
const allThumbnails = galleryThumbnails.querySelectorAll('.thumbnail');
const currentIndex = Array.from(allThumbnails).indexOf(currentThumbnail);
// Find next thumbnail or wrap to first
const nextThumbnail = currentIndex < allThumbnails.length - 1
? allThumbnails[currentIndex + 1]
: allThumbnails[0];
nextThumbnail.click();
nextThumbnail.scrollIntoView({ behavior: 'smooth', block: 'center' });
} else {
// Scroll only mode
const thumbnailList = galleryThumbnails.querySelector('.thumbnail-list');
if (thumbnailList) {
thumbnailList.scrollBy({ top: 100, behavior: 'smooth' });
}
}
});
}
function matchGalleryHeights() {
log('Running matchGalleryHeights...');
const galleryViewer = document.querySelector('[id*="GalleryViewer"]');
const galleryThumbnails = document.querySelector('[id*="GalleryThumbnails"]');
log('Elements found:', {
galleryViewer: !!galleryViewer,
galleryThumbnails: !!galleryThumbnails
});
if (galleryViewer && galleryThumbnails) {
const viewerHeight = galleryViewer.offsetHeight;
log('Gallery viewer height:', viewerHeight);
galleryThumbnails.style.height = `${viewerHeight}px`;
setTimeout(() => {
const newThumbnailsHeight = galleryThumbnails.offsetHeight;
log('Height after update:', {
newThumbnailsHeight,
expectedHeight: viewerHeight,
success: newThumbnailsHeight === viewerHeight
});
}, 0);
} else {
log('Missing required elements:', {
galleryViewer: !galleryViewer,
galleryThumbnails: !galleryThumbnails
});
}
}
return {
init: function () {
document.addEventListener("DOMContentLoaded", function () {
matchGalleryHeights();
addScrollButtons();
watchThumbnailSelection();
});
window.addEventListener("resize", function () {
matchGalleryHeights();
});
window.addEventListener("load", function () {
matchGalleryHeights();
addScrollButtons();
watchThumbnailSelection();
});
window.addEventListener("scroll", function () {
matchGalleryHeights();
});
}
};
})();
ezfyVerticalThumbnails.init();
</script>
{% schema %}
{
"name": "EZFY Vertical Thumbnails",
"class": "ezfy-vertical-thumbnails",
"disabled_on": {
"groups": ["header", "footer"]
},
"settings": [
{
"type": "checkbox",
"id": "hide_scrollbar",
"label": "Hide Scrollbar",
"default": false,
"info": "Hide the scrollbar while maintaining scroll functionality"
},
{
"type": "select",
"id": "thumbnail_aspect_desktop",
"label": "Desktop Thumbnail Aspect Ratio",
"options": [
{
"value": "original",
"label": "Original"
},
{
"value": "square",
"label": "Square"
}
],
"default": "square",
"info": "Choose between original image aspect ratio or square thumbnails on desktop"
},
{
"type": "select",
"id": "thumbnail_aspect_mobile",
"label": "Mobile Thumbnail Aspect Ratio",
"options": [
{
"value": "original",
"label": "Original"
},
{
"value": "square",
"label": "Square"
}
],
"default": "square",
"info": "Choose between original image aspect ratio or square thumbnails on mobile"
},
{
"type": "select",
"id": "arrow_behavior",
"label": "Arrow Behavior",
"options": [
{
"value": "navigate",
"label": "Navigate to Next/Previous Thumbnail"
},
{
"value": "scroll",
"label": "Scroll Only"
}
],
"default": "navigate",
"info": "Choose whether arrows navigate to next/previous thumbnail or just scroll"
},
{
"type": "checkbox",
"id": "show_arrows_desktop",
"label": "Show Arrows on Desktop",
"default": true,
"info": "Show navigation arrows on desktop"
},
{
"type": "checkbox",
"id": "show_arrows_mobile",
"label": "Show Arrows on Mobile",
"default": true,
"info": "Show navigation arrows on mobile"
},
{
"type": "checkbox",
"id": "show_arrows_on_hover",
"label": "Show Arrows on Hover",
"default": false,
"info": "Only show arrows when hovering over thumbnails"
},
{
"type": "color",
"id": "arrow_bg_color",
"label": "Arrow Background Color",
"default": "#ffffff"
},
{
"type": "range",
"id": "arrow_default_opacity",
"min": 0,
"max": 100,
"step": 5,
"unit": "%",
"label": "Arrow Default Opacity",
"default": 80,
"info": "Default opacity of the arrows"
},
{
"type": "range",
"id": "arrow_opacity",
"min": 0,
"max": 100,
"step": 5,
"unit": "%",
"label": "Arrow Opacity",
"default": 80,
"info": "Arrow opacity when not hovering"
},
{
"type": "range",
"id": "arrow_hover_opacity",
"min": 0,
"max": 100,
"step": 5,
"unit": "%",
"label": "Arrow Hover Opacity",
"default": 100,
"info": "Arrow opacity when hovering"
},
{
"type": "range",
"id": "border_width",
"min": 1,
"max": 5,
"step": 1,
"unit": "px",
"label": "Thumbnail Border Width",
"default": 1
},
{
"type": "color",
"id": "border_color",
"label": "Thumbnail Border Color",
"default": "#000000"
},
{
"type": "range",
"id": "desktop_gap",
"min": 0,
"max": 50,
"step": 1,
"unit": "px",
"label": "Desktop Gap",
"default": 20,
"info": "Space between thumbnails and main image on desktop"
},
{
"type": "range",
"id": "mobile_gap",
"min": 0,
"max": 50,
"step": 1,
"unit": "px",
"label": "Mobile Gap",
"default": 20,
"info": "Space between thumbnails and main image on mobile"
},
{
"type": "number",
"id": "desktop_margin_bottom",
"label": "Desktop Margin Bottom",
"default": 20,
"info": "Bottom margin of the gallery on desktop (in pixels)"
},
{
"type": "number",
"id": "mobile_margin_bottom",
"label": "Mobile Margin Bottom",
"default": 20,
"info": "Bottom margin of the gallery on mobile (in pixels)"
},
{
"type": "checkbox",
"id": "show_desktop",
"label": "Show on Desktop",
"default": true,
"info": "Show vertical thumbnails on desktop"
},
{
"type": "checkbox",
"id": "show_mobile",
"label": "Show on Mobile",
"default": true,
"info": "Show vertical thumbnails on mobile"
},
{
"type": "checkbox",
"id": "display_arrow_above_desktop",
"label": "Display Arrow Above Image (Desktop)",
"default": false,
"info": "Display the top arrow above the thumbnails instead of overlaying it"
},
{
"type": "checkbox",
"id": "display_arrow_above_mobile",
"label": "Display Arrow Above Image (Mobile)",
"default": false,
"info": "Display the top arrow above the thumbnails instead of overlaying it"
}
],
"presets": [
{
"name": "EZFY Vertical Thumbnails"
}
]
}
{% endschema %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment