Product image carousel in shop categories
The individual product pages have nifty arrows on the side of the image preview to scroll through the images of a product, these are called “carousel”. I wanted that functionality extended to the category view - to be able to quickly scroll product images without entering the individual product page.
HTML:
JAVASCRIPT:
<script>
document.addEventListener('DOMContentLoaded', function() {
const subString = 'shop';
const subStringTwo = 'shop/p/';
const getURL = window.location.href;
if (getURL.includes(subString) && !getURL.includes(subStringTwo)) {
const headerActions = document.querySelector('.header-actions');
let isTouch = false;
function checkHeader() {
const styles = window.getComputedStyle(headerActions);
isTouch = styles.getPropertyValue('display') !== 'flex';
}
checkHeader();
function cloneImageArrows() {
const products = document.querySelectorAll('.product-lists-item');
products.forEach((product, index) => {
const allImages = product.querySelectorAll('.grid-item-image');
if (allImages.length >= 2) {
const clonedElement = document.createElement('div');
const productImage = product.querySelector('.grid-image');
productImage.prepend(clonedElement);
clonedElement.id = `carousel${index + 1}`;
clonedElement.classList.add('carousel', 'categoryArrows', 'ProductItem-gallery-carousel-controls');
const leftArrow = document.createElement('div');
const rightArrow = document.createElement('div');
clonedElement.appendChild(leftArrow);
clonedElement.appendChild(rightArrow);
leftArrow.classList.add('arrowButton', 'arrowPrev', 'ProductItem-gallery-prev', 'product-item-gallery-carousel-control');
rightArrow.classList.add('arrowButton', 'arrowNext', 'ProductItem-gallery-next', 'product-item-gallery-carousel-control');
function adjustImageArrows() {
if (!isTouch) {
leftArrow.style.position = 'absolute';
leftArrow.style.left = '-14%';
leftArrow.style.transform = 'scale(0.33)';
rightArrow.style.position = 'absolute';
rightArrow.style.right = '-14%';
rightArrow.style.transform = 'scale(0.33)';
} else {
leftArrow.style.position = 'absolute';
leftArrow.style.left = '0%';
leftArrow.style.transform = 'scale(1.2)';
rightArrow.style.position = 'absolute';
rightArrow.style.right = '0%';
rightArrow.style.transform = 'scale(1.2)';
}
}
adjustImageArrows();
allImages.forEach((image, i) => {
if (i !== 0) image.style.display = 'none';
});
productImage.addEventListener('click', function(event) {
const clickedArrow = event.target.closest('.arrowButton');
if (!clickedArrow) return;
event.preventDefault();
const direction = clickedArrow.classList.contains('arrowPrev') ? 'left' : 'right';
handleArrowClick(direction, allImages);
});
function handleArrowClick(direction, images) {
const imagesArray = Array.from(images);
const activeImage = imagesArray.find(image => image.style.display === 'block');
const currentIndex = imagesArray.indexOf(activeImage);
let newIndex;
if (direction === 'left') {
newIndex = currentIndex > 0 ? currentIndex - 1 : imagesArray.length - 1;
} else {
newIndex = currentIndex < imagesArray.length - 1 ? currentIndex + 1 : 0;
}
activeImage.style.display = 'none';
activeImage.classList.remove('active');
imagesArray[newIndex].classList.add('active');
imagesArray[newIndex].style.display = 'block';
imagesArray[newIndex].classList.remove('grid-image-hover');
}
window.addEventListener('resize', function() {
const prevIsTouch = isTouch;
checkHeader();
if (isTouch !== prevIsTouch) {
adjustImageArrows();
}
});
}
});
}
cloneImageArrows();
}
});
</script>
CSS:
//PRODUCT CATEGORY CAROUSEL//
.product-item-gallery-carousel-control::after {
font-weight: bold;
border-right: 3px solid black !important;
border-top: 3px solid black !important;
border-image: linear-gradient(45deg, rgba(0,0,0,0) 50%, rgba(0,0,0,1) 100%);
border-image-slice: 1;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
transition: all 1s ease;
}
.product-item-gallery-carousel-control:hover::after {
background: linear-gradient(45deg, rgba(0,0,0,0) 50%, rgba(255,199,0,0.8) 100%,);
}
.carousel {
z-index: 9999;
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
.grid-item-image {
color: transparent;
opacity: 0% !important;
transition: all 1s ease-in-out !important;
}
.grid-item-image.active {
opacity: 100% !important;
display: block;
}

COMMENTS:
Leave a comment: