JS – Responsive pagination slider
Pagination in Views is one of the most powerful and flexible features of Toolset Views. It provides several options to achieve different layouts, such as a typical blog grid with pagination, an article slider, a multi-article slider, or an image slider. It is also great for website optimization, as it prevents loading all entries at once and only loads the entries for the current page. Additionally, it handles URL updates and SEO efficiently.
However, one of its few drawbacks is that it is not fully responsive. It is not possible to adjust the number of paginated items based on the viewport size. Also, it is not possible to change the number of paginated items dynamically using attributes like Limit and Offset.
To work around this limitation, you can implement a responsive pagination slider using JavaScript, especially when you want to load a limited number of entries. This is useful, for example, when creating a multi-article slider, where you display 4 articles per row on desktop, 2 or 3 articles per row on tablet, and just 1 article per row on mobile. In such cases, it’s a good idea to limit the view to load only the latest 8 or 12 articles.
[wpv-layout-start] [wpv-items-found] <div class="my-slider-container"> <div class="my-slider-grid"> <!-- wpv-loop-start --> <wpv-loop> <div class="my-slider-column"> [wpv-post-body view_template="my-item"] </div> </wpv-loop> <!-- wpv-loop-end --> </div> <div class="my-slider-pagination"> <div class="my-slider-page-item page-item-prev"> <a class="my-slider-page-link prev-arrow" href="#">❮</a> </div> <div class="my-slider-page-item page-item-next"> <a class="my-slider-page-link next-arrow" href="#">❯</a> </div> </div> </div> [/wpv-items-found] [wpv-no-items-found][/wpv-no-items-found] [wpv-layout-end]
In the JS editor, you will need to add the following code:
// Custom pagination slider
document.addEventListener("DOMContentLoaded", function () {
const sliders = document.querySelectorAll(".my-slider-container");
sliders.forEach(sliderContainer => {
const slider = sliderContainer.querySelector(".my-slider-grid");
const prevArrow = sliderContainer.querySelector(".prev-arrow");
const nextArrow = sliderContainer.querySelector(".next-arrow");
let currentSlide = 0;
let itemsPerPage = 4; // Default for large screens
let startX = 0;
let endX = 0;
let isSwiping = false;
let isDragging = false; // Flag to check if the user is dragging
function updateSlider() {
let width = window.innerWidth;
if (width <= 599) {
itemsPerPage = 1;
} else if (width <= 980) {
itemsPerPage = 2;
} else {
itemsPerPage = 4;
}
const slideWidth = sliderContainer.clientWidth / itemsPerPage;
slider.style.transform = `translateX(-${currentSlide * slideWidth}px)`;
// Hide/show arrows based on current slide position
if (currentSlide === 0) {
prevArrow.style.display = 'none';
} else {
prevArrow.style.display = 'block';
}
const totalItems = slider.children.length;
if (currentSlide >= totalItems - itemsPerPage) {
nextArrow.style.display = 'none';
} else {
nextArrow.style.display = 'block';
}
}
// Arrow click event listeners
nextArrow.addEventListener("click", function (e) {
e.preventDefault();
const totalItems = slider.children.length;
if (currentSlide < totalItems - itemsPerPage) {
currentSlide++;
updateSlider();
}
});
prevArrow.addEventListener("click", function (e) {
e.preventDefault();
if (currentSlide > 0) {
currentSlide--;
updateSlider();
}
});
// Touch event listeners for mobile swipe functionality
slider.addEventListener("touchstart", function (e) {
startX = e.touches[0].clientX;
isSwiping = true;
isDragging = false; // Reset dragging flag on touchstart
});
slider.addEventListener("touchmove", function (e) {
if (isSwiping) {
endX = e.touches[0].clientX;
if (Math.abs(endX - startX) > 10) { // Only consider as drag if moved more than 10px
isDragging = true;
}
}
});
slider.addEventListener("touchend", function (e) {
if (isSwiping && isDragging) { // Trigger swipe only if there was a drag
const swipeDistance = endX - startX;
const threshold = 50; // Minimum swipe distance to trigger
if (Math.abs(swipeDistance) > threshold) {
if (swipeDistance > 0) {
// Swipe right (previous)
if (currentSlide > 0) {
currentSlide--;
}
} else {
// Swipe left (next)
const totalItems = slider.children.length;
if (currentSlide < totalItems - itemsPerPage) {
currentSlide++;
}
}
updateSlider();
}
}
isSwiping = false;
});
window.addEventListener("resize", updateSlider);
updateSlider(); // Initialize on page load
});
});
