To create a draggable card or image slider using HTML, CSS, and vanilla JavaScript, follow the given steps line by line:
- Create a folder. You can name this folder whatever you want, and inside this folder, create the mentioned files.
- Create an
index.html
file. The file name must be index and its extension .html - Create a
style.css
file. The file name must be style and its extension .css - Create a
script.js
file. The file name must be script and its extension .js - Download the images folder from Google Drive and put this folder inside the project folder. This folder has all the images that will be used for this slider.
To start, add the following HTML codes to your index.html
file to create a basic layout for our card slider. This code includes a ul element to hold all of the li elements, which represent each card in the slider. Additionally, the code includes next and previous icons for navigation through the slider.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Infinite Card Slider JavaScript | Pravarti-tech</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Fontawesome Link for Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
<script src="script.js" defer></script>
</head>
<body>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<ul class="carousel">
<li class="card">
<div class="img"><img src="https://img.freepik.com/premium-photo/coaching-motivation-happy-proud-business-leader-meeting-with-diverse-colleagues-office-portrait-male-smiling-during-training-with-workers-discussing-improvement-strategy-planning_590464-81771.jpg" alt="img" draggable="false"></div>
<h2>Blanche Pearson</h2>
<span>Sales Manager</span>
</li>
<li class="card">
<div class="img"><img src="https://www.achievers.com/wp-content/uploads/2020/05/05-27-20-2.jpg" alt="img" draggable="false"></div>
<h2>Joenas Brauers</h2>
<span>Web Developer</span>
</li>
<li class="card">
<div class="img"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR_PdJ0Nw5ADvr9NzVeuogCLnxzu_XJGYn20tShrMXDZvVqQgPUx3z6b_Ubz-DCWsZc4ts&usqp=CAU" alt="img" draggable="false"></div>
<h2>Lariach French</h2>
<span>Online Teacher</span>
</li>
<li class="card">
<div class="img"><img src="https://img.freepik.com/free-photo/young-person-during-intership_23-2149315588.jpg?w=2000" alt="img" draggable="false"></div>
<h2>James Khosravi</h2>
<span>Freelancer</span>
</li>
<li class="card">
<div class="img"><img src="https://cdn.xxl.thumbs.canstockphoto.com/businesswoman-business-woman-at-the-office-ready-to-work-stock-photograph_csp28303495.jpg" alt="img" draggable="false"></div>
<h2>Kristina Zasiadko</h2>
<span>Bank Manager</span>
</li>
<li class="card">
<div class="img"><img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8ZW1wbG95ZWV8ZW58MHx8MHx8fDA%3D&w=1000&q=80" alt="img" draggable="false"></div>
<h2>Donald Horton</h2>
<span>App Designer</span>
</li>
</ul>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</body>
</html>
Next, add the following CSS codes to your style.css
file to style the cards and position the next and previous icons. You can customize this code to your liking by adjusting the color, font, size, and other CSS properties. Once you’ve added the CSS code, you should see three cards displayed on your browser screen.
/* Import Google font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
display: flex;
padding: 0 35px;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(to left top, #031A9A, #8B53FF);
}
.wrapper {
max-width: 1100px;
width: 100%;
position: relative;
}
.wrapper i {
top: 50%;
height: 50px;
width: 50px;
cursor: pointer;
font-size: 1.25rem;
position: absolute;
text-align: center;
line-height: 50px;
background: #fff;
border-radius: 50%;
box-shadow: 0 3px 6px rgba(0,0,0,0.23);
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active{
transform: translateY(-50%) scale(0.85);
}
.wrapper i:first-child{
left: -22px;
}
.wrapper i:last-child{
right: -22px;
}
.wrapper .carousel{
display: grid;
grid-auto-flow: column;
grid-auto-columns: calc((100% / 3) - 12px);
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 16px;
border-radius: 8px;
scroll-behavior: smooth;
scrollbar-width: none;
}
.carousel::-webkit-scrollbar {
display: none;
}
.carousel.no-transition {
scroll-behavior: auto;
}
.carousel.dragging {
scroll-snap-type: none;
scroll-behavior: auto;
}
.carousel.dragging .card {
cursor: grab;
user-select: none;
}
.carousel :where(.card, .img) {
display: flex;
justify-content: center;
align-items: center;
}
.carousel .card {
scroll-snap-align: start;
height: 342px;
list-style: none;
background: #fff;
cursor: pointer;
padding-bottom: 15px;
flex-direction: column;
border-radius: 8px;
}
.carousel .card .img {
background: #8B53FF;
height: 148px;
width: 148px;
border-radius: 50%;
}
.card .img img {
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #fff;
}
.carousel .card h2 {
font-weight: 500;
font-size: 1.56rem;
margin: 30px 0 5px;
}
.carousel .card span {
color: #6A6D78;
font-size: 1.31rem;
}
@media screen and (max-width: 900px) {
.wrapper .carousel {
grid-auto-columns: calc((100% / 2) - 9px);
}
}
@media screen and (max-width: 600px) {
.wrapper .carousel {
grid-auto-columns: 100%;
}
}
Finally, add the following JavaScript code to your script.js file to make the cards draggable, autoplayable, and create an infinite slider
const wrapper = document.querySelector(".wrapper");
const carousel = document.querySelector(".carousel");
const firstCardWidth = carousel.querySelector(".card").offsetWidth;
const arrowBtns = document.querySelectorAll(".wrapper i");
const carouselChildrens = [...carousel.children];
let isDragging = false, isAutoPlay = true, startX, startScrollLeft, timeoutId;
// Get the number of cards that can fit in the carousel at once
let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);
// Insert copies of the last few cards to beginning of carousel for infinite scrolling
carouselChildrens.slice(-cardPerView).reverse().forEach(card => {
carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
});
// Insert copies of the first few cards to end of carousel for infinite scrolling
carouselChildrens.slice(0, cardPerView).forEach(card => {
carousel.insertAdjacentHTML("beforeend", card.outerHTML);
});
// Scroll the carousel at appropriate postition to hide first few duplicate cards on Firefox
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
// Add event listeners for the arrow buttons to scroll the carousel left and right
arrowBtns.forEach(btn => {
btn.addEventListener("click", () => {
carousel.scrollLeft += btn.id == "left" ? -firstCardWidth : firstCardWidth;
});
});
const dragStart = (e) => {
isDragging = true;
carousel.classList.add("dragging");
// Records the initial cursor and scroll position of the carousel
startX = e.pageX;
startScrollLeft = carousel.scrollLeft;
}
const dragging = (e) => {
if(!isDragging) return; // if isDragging is false return from here
// Updates the scroll position of the carousel based on the cursor movement
carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
}
const dragStop = () => {
isDragging = false;
carousel.classList.remove("dragging");
}
const infiniteScroll = () => {
// If the carousel is at the beginning, scroll to the end
if(carousel.scrollLeft === 0) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.scrollWidth - (2 * carousel.offsetWidth);
carousel.classList.remove("no-transition");
}
// If the carousel is at the end, scroll to the beginning
else if(Math.ceil(carousel.scrollLeft) === carousel.scrollWidth - carousel.offsetWidth) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
}
// Clear existing timeout & start autoplay if mouse is not hovering over carousel
clearTimeout(timeoutId);
if(!wrapper.matches(":hover")) autoPlay();
}
const autoPlay = () => {
if(window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false
// Autoplay the carousel after every 2500 ms
timeoutId = setTimeout(() => carousel.scrollLeft += firstCardWidth, 2500);
}
autoPlay();
carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", dragStop);
carousel.addEventListener("scroll", infiniteScroll);
wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId));
wrapper.addEventListener("mouseleave", autoPlay);
👁View Live Demo
0 Comments