Articles on: Seller Cases
This article is also available in:

Enable sticky gallery on mobile

In this article, we will walk you through the steps to implement the sticky gallery feature on mobile view. A little coding skill is required. However, if you follow the guide closely, you will be able to implement it on your own pretty easily!


This is how it should look once you are done:





Steps to enable sticky gallery on mobile


  • Navigate to your  Online Store > Themes > Edit code.



  • Create tee-sticky-gallery.js file inside Assets folder.



  • Find the selector of the element that wraps the gallery in your theme. In the example below, since we are using Dawn Theme, it should be .grid__item.product__media-wrapper


The element you choose should be the whole product gallery of your product template



  • Add the following code to the tee-sticky-gallery.js file. Declare the variable galleryWrapperSelector with the selector found in the previous step. In this case, it should be .grid__item.product__media-wrapper with Dawn Theme.


If you are using other Theme than Dawn, please change the selector inside the 3rd line of the JS below!


document.addEventListener('DOMContentLoaded', () => {
const fixedLivePreview = () => {
const galleryWrapperSelector = '.grid__item.product__media-wrapper';
const $gallery = document.querySelector(galleryWrapperSelector);

if (!$gallery) return;

const SCALE = 0.7;
const PADDING_Y = 30;
const SAFETY_SCROLLING_RANGE = 100;

const style = document.createElement('style');
style.innerHTML = `
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} {
z-index: 9999;
}
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} .tee-gallery-content {
background: #fff;
display: flex;
justify-content: center;
left: 0;
position: fixed;
top: 0;
width: 100vw;
z-index: 99;
padding: ${PADDING_Y}px 0;
}
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} #tee-gallery {
transform: scale(${SCALE});
transform-origin: top center;
}
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} .tee-gallery {
width: auto;
}
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} .tee-thumbnails,
.gallery--sticky:not(.gallery--sticky--hide) ${galleryWrapperSelector} .tee-slider__dots {
display: none;
}
.gallery--sticky:not(.gallery--sticky--hide) .gallery--close-button {
display: block;
}
.gallery--sticky.gallery--sticky--hide .sticky-gallery-button {
display: block;
}
.sticky-gallery-button {
background-color: #fff;
background-image: url('data:image/svg+xml;utf8,<svg version="1.1" id="Layer_2_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><g><path d="M114.5,79.1C95,79.1,79.1,95,79.1,114.5v283c0,19.5,15.8,35.4,35.4,35.4h283c19.5,0,35.4-15.8,35.4-35.4v-283 c0-19.5-15.8-35.4-35.4-35.4H114.5z M114.5,409.3c-6.5,0-11.8-5.3-11.8-11.8V308l94.3-94.3l195.6,195.6H114.5z M409.3,392.7 L331.6,315l30.5-30.5l47.2,47.2V392.7z M409.3,114.5v183.8l-38.8-38.9c-4.6-4.6-12.1-4.7-16.7-0.1c0,0,0,0-0.1,0.1L315,298.3 L205.4,188.7c-4.6-4.6-12.1-4.7-16.7-0.1c0,0,0,0-0.1,0.1l-86,86.1V114.5c0-6.5,5.3-11.8,11.8-11.8h283 C404,102.7,409.3,108,409.3,114.5z"/><path d="M326.7,138.1c-26,0-47.2,21.1-47.2,47.2s21.1,47.2,47.2,47.2s47.2-21.1,47.2-47.2S352.8,138.1,326.7,138.1z M326.7,208.8 c-13,0-23.6-10.6-23.6-23.6s10.6-23.6,23.6-23.6s23.6,10.6,23.6,23.6S339.8,208.8,326.7,208.8z"/><path d="M23.7,35c0,0,0.1-4.9,3.3-7.9c3.5-3.4,8.1-3.5,8.1-3.5l89.6,0c0-19.2,0-23.6,0-23.6L34.9,0C15.6,0,0,15.6,0,34.9l0,89.8 l23.7,0V35z"/><path d="M484.9,26.9c3.4,3.5,3.5,8.1,3.5,8.1l0,89.6c19.2,0,23.6,0,23.6,0l0-89.8C512,15.6,496.4,0,477.1,0l-89.8,0l0,23.7H477 C477,23.7,482,23.8,484.9,26.9z"/><path d="M488.3,477c0,0-0.1,4.9-3.3,7.9c-3.5,3.4-8.1,3.5-8.1,3.5l-89.6,0c0,19.2,0,23.6,0,23.6l89.8,0c19.2,0,34.8-15.6,34.8-34.8 l0-89.8l-23.7,0V477z"/><path d="M27.1,485.1c-3.4-3.5-3.5-8.1-3.5-8.1l0-89.6c-19.2,0-23.6,0-23.6,0l0,89.8C0,496.4,15.6,512,34.9,512l89.8,0l0-23.7H35 C35,488.3,30,488.2,27.1,485.1z"/></g></svg>');
background-position: center;
background-repeat: no-repeat;
background-size: 20px 20px;
border-radius: 50%;
box-shadow: 0 2px 5px 3px rgba(0, 0, 0, .15);
display: none;
height: 40px;
position: fixed;
right: 20px;
top: 100px;
width: 40px;
z-index: 999;
}
.gallery--close-button {
background-image: url('data:image/svg+xml;utf8,<svg height="329pt" viewBox="0 0 329.26933 329" width="329pt" xmlns="http://www.w3.org/2000/svg"><path d="m194.800781 164.769531 128.210938-128.214843c8.34375-8.339844 8.34375-21.824219 0-30.164063-8.339844-8.339844-21.824219-8.339844-30.164063 0l-128.214844 128.214844-128.210937-128.214844c-8.34375-8.339844-21.824219-8.339844-30.164063 0-8.34375 8.339844-8.34375 21.824219 0 30.164063l128.210938 128.214843-128.210938 128.214844c-8.34375 8.339844-8.34375 21.824219 0 30.164063 4.15625 4.160156 9.621094 6.25 15.082032 6.25 5.460937 0 10.921875-2.089844 15.082031-6.25l128.210937-128.214844 128.214844 128.214844c4.160156 4.160156 9.621094 6.25 15.082032 6.25 5.460937 0 10.921874-2.089844 15.082031-6.25 8.34375-8.339844 8.34375-21.824219 0-30.164063zm0 0"/></svg>');
background-position: center;
background-repeat: no-repeat;
background-size: 16px 16px;
display: none;
height: 16px;
opacity: 0.5;
position: fixed;
right: 20px;
top: 20px;
width: 16px;
z-index: 1000;
}
.sticky-gallery-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
background: #fff;
box-shadow: 0 2px 5px 3px rgba(0, 0, 0, .15);
z-index: 999;
display: none;
}
.gallery--sticky--hide .sticky-gallery-mask {
display: none !important;
}
`;
document.head.appendChild(style);

let hasStickyButton = false;
let hasCloseButton = false;
let isSticky = false;
let lastCheckScrollY = null;
let maskEl = null;

let originalWrapperHeight = 0;

const initialGalleryRect = $gallery.getBoundingClientRect();
const stickyCondHeight =
(initialGalleryRect.height || 0) + PADDING_Y * 2;

const ensureMask = () => {
if (maskEl) return;
maskEl = document.createElement('div');
maskEl.className = 'sticky-gallery-mask';
document.body.appendChild(maskEl);
};

const updateMaskHeight = height => {
ensureMask();
if (!height) {
maskEl.style.display = 'none';
maskEl.style.removeProperty('height');
return;
}
maskEl.style.display = 'block';
maskEl.style.height = `${height}px`;
};

const getOverlayHeight = () => {
const content = document.querySelector(
`${galleryWrapperSelector} .tee-gallery-content`
);
if (content) {
const rect = content.getBoundingClientRect();
return rect.height;
}
const rect = $gallery.getBoundingClientRect();
return rect.height || 0;
};

const applyOverlayLayout = () => {
const h = getOverlayHeight();
if (!h) return;

if (originalWrapperHeight) {
$gallery.style.height = `${originalWrapperHeight}px`;
}
$gallery.style.display = 'block';

updateMaskHeight(h);
};

const clearOverlayLayout = () => {
$gallery.style.removeProperty('height');
$gallery.style.removeProperty('display');
updateMaskHeight(0);
};

const onScroll = () => {
const currentY = window.scrollY || window.pageYOffset || 0;

if (
lastCheckScrollY !== null &&
Math.abs(currentY - lastCheckScrollY) < SAFETY_SCROLLING_RANGE
) {
if (isSticky) {
const h = getOverlayHeight();
if (h) updateMaskHeight(h);
}
return;
}
lastCheckScrollY = currentY;

const $teeGallery = document.querySelector(
`${galleryWrapperSelector} #tee-gallery`
);
if (!$teeGallery) return;

if (!hasStickyButton) {
const stickyButton = document.createElement('div');
stickyButton.className = 'sticky-gallery-button';
stickyButton.addEventListener('click', e => {
e.preventDefault();
document.body.classList.remove('gallery--sticky--hide');
requestAnimationFrame(() => {
applyOverlayLayout();
});
});
document.body.appendChild(stickyButton);
hasStickyButton = true;
window.dispatchEvent(new Event('resize'));
}

if (!hasCloseButton) {
const closeButton = document.createElement('div');
closeButton.className = 'gallery--close-button';
closeButton.addEventListener('click', e => {
e.preventDefault();
document.body.classList.add('gallery--sticky--hide');
clearOverlayLayout();
});
document.body.appendChild(closeButton);
hasCloseButton = true;
}

const galleryBottom = $gallery.getBoundingClientRect().bottom;
const tForm = document.getElementById('tee-artwork-form');
if (!tForm) return;

const tFormBottom = tForm.getBoundingClientRect().bottom;

if (galleryBottom < 0 && tFormBottom > stickyCondHeight && !isSticky) {

originalWrapperHeight = $gallery.getBoundingClientRect().height;

document.body.classList.add('gallery--sticky');
requestAnimationFrame(() => {
applyOverlayLayout();
});
isSticky = true;
window.dispatchEvent(new Event('resize'));
}

if (
isSticky &&
(tFormBottom < stickyCondHeight || galleryBottom > 0)
) {
document.body.classList.remove('gallery--sticky');
clearOverlayLayout();
isSticky = false;
window.dispatchEvent(new Event('resize'));
}
};

window.addEventListener('scroll', onScroll, { passive: true });
};

const w = window.innerWidth;
const h = window.innerHeight;

if (h / w > 1.5 && w < 768) {
setTimeout(fixedLivePreview, 2000);
}
});


It should look like this once you copied the code:



  • Open the theme.liquid file and add the following code snippet just before </head> tag.


{{ 'tee-sticky-gallery.js' | asset_url | script_tag }}




  • Refresh the product page and see the result.



Notes

  • You need to accurately identify the selector of the gallery wrapper element for the code snippet to function correctly as intended.


  • The Customers will be able to toggle the sticky gallery should it get it the way of the Customization Form.




If you have trouble implementing this feature, please be sure to reach out to our Support Team!

Updated on: 29/05/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!