I’m using Glide.js along with Twig and vanilla JavaScript to create a gallery with one main image and a thumbnail slider. The thumbnails should display vertically (or horizontally on certain breakpoints), and everything works after I open DevTools or resize the window — but on initial load, the layout is broken (thumbnails are misaligned or not transformed correctly).
Here’s how I’m mounting everything:
window.onload = function () {
const glideMain = new Glide('.glide-main', {
type: 'carousel',
perView: 1,
autoplay: false,
gap: 0,
animationDuration: 500,
});
const glideThumb = new Glide('.glide-thumb', {
type: 'slider',
focusAt: 0,
dragThreshold: 0,
animationDuration: 500,
});
const thumbSlides = document.querySelectorAll('.glide-thumb .glide__slide');
// Function to apply z-index fix
function applyZIndexFix() {
document.querySelectorAll('.glide__thumb, .glide__thumb > img').forEach(el => {
el.style.zIndex = '999';
});
}
thumbSlides.forEach((slide, index) => {
slide.addEventListener('click', function (e) {
e.preventDefault();
glideMain.go('=' + index);
setActiveThumbnail(index);
});
});
function setActiveThumbnail(index) {
thumbSlides.forEach(slide => slide.classList.remove('active'));
if (thumbSlides[index]) {
thumbSlides[index].classList.add('active');
}
applyZIndexFix();
}
setActiveThumbnail(0);
function updateThumbTransformVertical(activeIndex) {
const thumbContainer = document.querySelector('.glide-thumb .glide__slides');
const containerHeight = document.querySelector('.glide-thumb').offsetHeight;
const totalSlides = thumbSlides.length;
const slideHeight = thumbSlides[0]?.offsetHeight + 10 || 0;
const maxTranslate = (totalSlides * slideHeight) - containerHeight;
const centerIndex = 2;
let translateY = 0;
if (activeIndex <= centerIndex) {
translateY = 0;
} else if (activeIndex >= totalSlides - centerIndex - 1) {
translateY = maxTranslate;
} else {
translateY = (activeIndex - centerIndex) * slideHeight;
}
if (activeIndex === totalSlides - 1 || activeIndex === totalSlides - 2 || activeIndex === totalSlides - 3) {
translateY -= 10;
}
thumbContainer.style.transition = 'transform 0.5s ease';
thumbContainer.style.transform = `translate3d(0, ${-translateY}px, 0)`;
applyZIndexFix();
}
function updateThumbTransformHorizontal(activeIndex) {
const thumbContainer = document.querySelector('.glide-thumb .glide__slides');
const containerWidth = document.querySelector('.glide-thumb').offsetWidth;
const totalSlides = thumbSlides.length;
const slideWidth = thumbSlides[0]?.offsetWidth + 10 || 0;
const maxTranslate = (totalSlides * slideWidth) - containerWidth;
const centerIndex = 2;
let translateX = 0;
if (activeIndex <= centerIndex) {
translateX = 0;
} else if (activeIndex >= totalSlides - centerIndex - 1) {
translateX = maxTranslate;
} else {
translateX = (activeIndex - centerIndex) * slideWidth;
}
thumbContainer.style.transition = 'transform 0.5s ease';
thumbContainer.style.transform = `translate3d(${ -translateX }px, 0, 0)`;
applyZIndexFix();
}
glideMain.on('run', function () {
setActiveThumbnail(glideMain.index);
const width = window.innerWidth;
if (width >= 768 && width <= 1131) {
updateThumbTransformHorizontal(glideMain.index);
} else {
updateThumbTransformVertical(glideMain.index);
}
});
glideMain.mount();
applyZIndexFix(); // Apply z-index after mounting
function checkScreenWidth() {
const width = window.innerWidth;
if (width >= 1132 || width < 768) {
document.querySelector('.glide-thumb').classList.remove('horizontal');
glideThumb.mount();
} else if (width >= 768 && width <= 1131) {
document.querySelector('.glide-thumb').classList.add('horizontal');
glideThumb.mount();
}
applyZIndexFix();
}
checkScreenWidth();
window.onresize = function () {
checkScreenWidth();
};
setTimeout(() => {
updateThumbTransformVertical(glideMain.index);
}, 100);
};
As I see initially it has width: 0 px and after triggering screen width it gets the real width value which is appropriate.


