Skip to main content

How to Create a Responsive Horizontal Scrolling Card Slider in JavaScript

· 7 min read
Kamlesh
Quality Assurance @TestKarts

Introduction:

Horizontal scrolling is a popular UI pattern used in many modern web applications. A horizontal card slider is a similar design pattern that allows users to scroll through a set of cards horizontally. In this tutorial, we'll be using JavaScript and CSS to create a horizontal card slider with forward and backward scrolling buttons. Horizontal Card slider with arrow

Features:

  • Step-by-step instructions: The post provides a detailed and easy-to-follow tutorial on how to create a horizontal scrolling card with forward and back buttons.

  • Interactive functionality: The post provides code that allows users to interact with the horizontal scrolling card by clicking on the forward and back buttons to slide the cards left or right.

  • End-of-scroll detection: The post includes code to detect when the horizontal scroll has reached either end, and disables the relevant button to prevent users from scrolling further.

  • Default state: The post explains how to set the default state of the horizontal scroll to be at the leftmost card and disable the back button.

  • Customizable code: The post provides code that can be customized to fit different design and functionality requirements.

Implementation:

To create a horizontal card slider, we first need to create a container element with a fixed width and overflow-x set to scroll. Inside the container, we'll add a set of card elements that are floated left and have a fixed width.

Next, we'll use JavaScript to detect when the slider reaches the left or right end and disable the corresponding arrow button. We'll also add event listeners to the arrow buttons to scroll the slider left or right when clicked.

Here's the complete code to implement a horizontal card slider with forward and backward scrolling buttons:

Here are the steps to follow:

Step 1: Create the HTML markup

Create an HTML element to hold the cards that will be horizontally scrolled. Inside this element, create a container for the cards that will be scrolled. Each card should be wrapped in a div element. Here's an example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script src="https://kit.fontawesome.com/a59b9b09ab.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<link rel="stylesheet" href="style.css" />
<title>Static Template</title>
</head>

<body>
<div class="cover">
<button class="left" onclick="leftScroll()">
<i class="fas fa-angle-double-left"></i>
</button>
<div class="scroll-images">
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-1-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0ZM9.283 4.002H7.971L6.072 5.385v1.271l1.834-1.318h.065V12h1.312V4.002Z"/>
</svg>
<h4>Card 1</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-2-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0ZM6.646 6.24c0-.691.493-1.306 1.336-1.306.756 0 1.313.492 1.313 1.236 0 .697-.469 1.23-.902 1.705l-2.971 3.293V12h5.344v-1.107H7.268v-.077l1.974-2.22.096-.107c.688-.763 1.287-1.428 1.287-2.43 0-1.266-1.031-2.215-2.613-2.215-1.758 0-2.637 1.19-2.637 2.402v.065h1.271v-.07Z"/>
</svg>
<h4>Card 2</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-3-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-8.082.414c.92 0 1.535.54 1.541 1.318.012.791-.615 1.36-1.588 1.354-.861-.006-1.482-.469-1.54-1.066H5.104c.047 1.177 1.05 2.144 2.754 2.144 1.653 0 2.954-.937 2.93-2.396-.023-1.278-1.031-1.846-1.734-1.916v-.07c.597-.1 1.505-.739 1.482-1.876-.03-1.177-1.043-2.074-2.637-2.062-1.675.006-2.59.984-2.625 2.12h1.248c.036-.556.557-1.054 1.348-1.054.785 0 1.348.486 1.348 1.195.006.715-.563 1.237-1.342 1.237h-.838v1.072h.879Z"/>
</svg>
<h4>Card 3</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-4-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0ZM7.519 5.057c-.886 1.418-1.772 2.838-2.542 4.265v1.12H8.85V12h1.26v-1.559h1.007V9.334H10.11V4.002H8.176c-.218.352-.438.703-.657 1.055ZM6.225 9.281v.053H8.85V5.063h-.065c-.867 1.33-1.787 2.806-2.56 4.218Z"/>
</svg>
<h4>Card 4</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-5-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-8.006 4.158c1.74 0 2.924-1.119 2.924-2.806 0-1.641-1.178-2.584-2.56-2.584-.897 0-1.442.421-1.612.68h-.064l.193-2.344h3.621V4.002H5.791L5.445 8.63h1.149c.193-.358.668-.809 1.435-.809.85 0 1.582.604 1.582 1.57 0 1.085-.779 1.682-1.57 1.682-.697 0-1.389-.31-1.53-1.031H5.276c.065 1.213 1.149 2.115 2.72 2.115Z"/>
</svg>
<h4>Card 5</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-6-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0ZM8.21 3.855c-1.868 0-3.116 1.395-3.116 4.407 0 1.183.228 2.039.597 2.642.569.926 1.477 1.254 2.409 1.254 1.629 0 2.847-1.013 2.847-2.783 0-1.676-1.254-2.555-2.508-2.555-1.125 0-1.752.61-1.98 1.155h-.082c-.012-1.946.727-3.036 1.805-3.036.802 0 1.213.457 1.312.815h1.29c-.06-.908-.962-1.899-2.573-1.899Zm-.099 4.008c-.92 0-1.564.65-1.564 1.576 0 1.032.703 1.635 1.558 1.635.868 0 1.553-.533 1.553-1.629 0-1.06-.744-1.582-1.547-1.582Z"/>
</svg>
<h4>Card 6</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-7-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0ZM5.37 5.11h3.972v.07L6.025 12H7.42l3.258-6.85V4.002H5.369v1.107Z"/>
</svg>
<h4>Card 7</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-8-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-5.03 1.803c0-1.248-.943-1.84-1.646-1.992v-.065c.598-.187 1.336-.72 1.336-1.781 0-1.225-1.084-2.121-2.654-2.121-1.57 0-2.66.896-2.66 2.12 0 1.044.709 1.589 1.33 1.782v.065c-.697.152-1.647.732-1.647 2.003 0 1.39 1.19 2.344 2.953 2.344 1.77 0 2.989-.96 2.989-2.355Zm-4.347-3.71c0 .739.586 1.255 1.383 1.255s1.377-.516 1.377-1.254c0-.733-.58-1.23-1.377-1.23s-1.383.497-1.383 1.23Zm-.281 3.645c0 .838.72 1.412 1.664 1.412.943 0 1.658-.574 1.658-1.412 0-.843-.715-1.424-1.658-1.424-.944 0-1.664.58-1.664 1.424Z"/>
</svg>
<h4>Card 8</h4>
</div>
<div class="child">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-9-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-8.223 4.146c2.104 0 3.123-1.464 3.123-4.3 0-3.147-1.459-4.014-2.97-4.014-1.63 0-2.871 1.02-2.871 2.73 0 1.706 1.171 2.667 2.566 2.667 1.06 0 1.7-.557 1.934-1.184h.076c.047 1.67-.475 3.023-1.834 3.023-.71 0-1.149-.363-1.248-.72H5.258c.094.908.926 1.798 2.52 1.798Zm.118-3.972c.808 0 1.535-.528 1.535-1.594s-.668-1.676-1.56-1.676c-.838 0-1.517.616-1.517 1.659 0 1.072.708 1.61 1.54 1.61Z"/>
</svg>
<h4>Card 9</h4>
</div>
</div>
<button class="right" onclick="rightScroll()">
<i class="fas fa-angle-double-right"></i>
</button>
</div>
</body>
</html>

Step 2: Add CSS

Add CSS to create the horizontal scroll effect. Set the scroll-container element to overflow-x: scroll to allow horizontal scrolling. Set the width of each card to the desired width and make sure they are displayed inline-block. Here's an example:

.cover {
position: relative;
padding: 0px 30px;
margin-top: 100px;
}

.left {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}

.right {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}

.scroll-images {
position: relative;
width: 100%;
padding: 40px 0px;
height: auto;
display: flex;
flex-wrap: nowrap;
overflow-x: hidden;
overflow-y: hidden;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
}

.child {
display: flex;
justify-content: center;
align-items: center;
min-width: 250px;
height: 200px;
padding: 0px 15px;
margin: 1px 10px;
border: 1px solid #f1f1f1;
overflow: hidden;
-webkit-box-shadow: 0px 0px 15px 2px rgb(0 0 0 / 10%);;
box-shadow: 0px 0px 15px 2px rgb(0 0 0 / 10%);;
}

.child img, .child > svg {
position: absolute;
margin-top: -195px;
width: 80px;
height: 80px;
object-fit: cover;
object-position: center;
border-radius: 50%;
background: #03A9F4;
}

.scroll-images::-webkit-scrollbar {
width: 5px;
height: 8px;
background-color: #aaa;
}

.scroll-images::-webkit-scrollbar-thumb {
background-color: black;
}

button {
background-color: transparent;
border: none;
outline: none;
cursor: pointer;
font-size: 25px;
}

Step 3: Add JavaScript

Add JavaScript to handle the scrolling and enable/disable the arrow buttons. Here's an example:

document.addEventListener("DOMContentLoaded", function () {
const scrollImages = document.querySelector(".scroll-images");
const scrollLength = scrollImages.scrollWidth - scrollImages.clientWidth;
const leftButton = document.querySelector(".left");
const rightButton = document.querySelector(".right");

function checkScroll() {
const currentScroll = scrollImages.scrollLeft;
if (currentScroll === 0) {
leftButton.setAttribute("disabled", "true");
rightButton.removeAttribute("disabled");
} else if (currentScroll === scrollLength) {
rightButton.setAttribute("disabled", "true");
leftButton.removeAttribute("disabled");
} else {
leftButton.removeAttribute("disabled");
rightButton.removeAttribute("disabled");
}
}

scrollImages.addEventListener("scroll", checkScroll);
window.addEventListener("resize", checkScroll);
checkScroll();

function leftScroll() {
scrollImages.scrollBy({
left: -200,
behavior: "smooth"
});
}

function rightScroll() {
scrollImages.scrollBy({
left: 200,
behavior: "smooth"
});
}

leftButton.addEventListener("click", leftScroll);
rightButton.addEventListener("click", rightScroll);
});

Customize the JavaScript to fit your specific needs. For example, you may need to change the width of each card or the amount that the scroll container scrolls when the arrow buttons are clicked.

And that's it! With these steps, you can create a card horizontal scrolling with forward and back arrow buttons that enable/disable depending on the scroll position.

Try on CodePen :-