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.jsfile insideAssetsfolder.

- 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

- Add the following code to the
tee-sticky-gallery.jsfile. Declare the variablegalleryWrapperSelectorwith the selector found in the previous step. In this case, it should be.grid__item.product__media-wrapperwith Dawn Theme.
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.liquidfile 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.

Updated on: 29/05/2026
Thank you!
