Untitled fiddle
by alyonani
HTML
<div class="team-slider">
<button id="left" class="team-arrow" aria-label="Previous">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<polyline points="15 6 9 12 15 18" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<ul class="team-carousel">
<li class="team-card">
<div class="team-img">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjkSVCBI69NxYIT6CUQ1wFiUOIJv-JZ9Uai1lUX9_S-g&s" alt="Atharv" draggable="false">
</div>
<h2>Atharv</h2>
<span>Founder</span>
<p class="team-desc">Passionate entrepreneur leading the vision and strategy of the company.</p>
<a target="_blank" rel="noopener noreferrer" href="https://example.com/atharv" class="team-btn">View Profile</a>
</li>
<li class="team-card">
<div class="team-img">
<img src="https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=600&auto=format&fit=crop&q=60" alt="Arjun" draggable="false">
</div>
<h2>Arjun</h2>
<span>Web Developer</span>
<p class="team-desc">Full-stack web developer creating modern and scalable solutions.</p>
<a target="_blank" rel="noopener noreferrer" href="#" class="team-btn">View Profile</a>
</li>
<li class="team-card">
<div class="team-img">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9SxmItTvkyQk0JORqWUL5Ga3eSoxie7tmJELiNRJ9dQ&s" alt="Riya" draggable="false">
</div>
<h2>Riya</h2>
<span>Graphics Designer</span>
<p class="team-desc">Creative designer turning ideas into stunning visuals.</p>
<a target="_blank" rel="noopener noreferrer" href="https://example.com/Riya" class="team-btn">View Profile</a>
</li>
<li class="team-card">
<div class="team-img">
<img...
CSS
<style>
.team-slider *,.team-slider *::before,.team-slider *::after{box-sizing:border-box}
.team-slider{max-width:1140px;width:100%;position:relative;margin:0 auto;padding:0 20px}
.team-arrow{position:absolute;top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center;width:46px;height:46px;padding:0;border-radius:50%;border:none;background:#fff;box-shadow:0 4px 12px rgba(0,0,0,0.15);cursor:pointer;z-index:10;transition:all 0.3s ease}
.team-arrow:hover{background:#8b53ff;color:#fff}
.team-arrow svg{display:block;width:18px;height:18px}
.team-arrow{color:#222}
.team-arrow#left{left:-5px}
.team-arrow#right{right:-5px}
.team-slider .team-carousel{display:grid;grid-auto-flow:column;grid-auto-columns:calc((100% / 3) - 12px);overflow-x:auto;scroll-snap-type:x mandatory;gap:18px;scroll-behavior:smooth;scrollbar-width:none;padding:15px 5px;margin:0;list-style:none}
.team-carousel::-webkit-scrollbar{display:none}
.team-carousel.no-transition{scroll-behavior:auto}
.team-carousel.dragging{scroll-snap-type:none;scroll-behavior:auto}
.team-carousel.dragging .team-card{cursor:grab;user-select:none}
.team-carousel .team-card{scroll-snap-align:start;min-height:420px;background:#fff;border-radius:12px;padding:25px 20px;display:flex;flex-direction:column;align-items:center;text-align:center;box-shadow:0 10px 20px rgba(0,0,0,0.05),0 2px 6px rgba(0,0,0,0.05);transition:transform 0.3s ease,box-shadow 0.3s ease}
.team-carousel .team-card:hover{transform:translateY(-5px);box-shadow:0 15px 30px rgba(139,83,255,0.15)}
.team-carousel .team-card .team-img{background:#8b53ff;height:140px;width:140px;border-radius:50%;overflow:hidden;display:flex;justify-content:center;align-items:center;margin-bottom:15px;flex-shrink:0}
.team-card .team-img img{width:132px;height:132px;border-radius:50%;object-fit:cover;border:4px solid #fff}
.team-carousel .team-card h2{font-weight:600;font-size:1.4rem;margin:5px 0 2px;color:#222}
.team-carousel...
JavaScript
<script>
const wrapper = document.querySelector(".team-slider");
const carousel = document.querySelector(".team-carousel");
const firstCard = carousel.querySelector(".team-card");
const arrowBtns = document.querySelectorAll(".team-arrow");
const dotsContainer = document.querySelector(".team-dots");
const carouselChildrens = [...carousel.children];
let isDragging = false, isAutoPlay = true, startX, startScrollLeft, timeoutId;
const getCardWidth = () => firstCard.offsetWidth + parseFloat(window.getComputedStyle(carousel).gap);
let firstCardWidth = getCardWidth();
let cardPerView = Math.round(carousel.offsetWidth / firstCard.offsetWidth);
carouselChildrens.slice(-cardPerView).reverse().forEach(card => {
carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
});
carouselChildrens.slice(0, cardPerView).forEach(card => {
carousel.insertAdjacentHTML("beforeend", card.outerHTML);
});
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
window.addEventListener('resize', () => {
firstCardWidth = getCardWidth();
});
arrowBtns.forEach(btn => {
btn.addEventListener("click", () => {
carousel.scrollLeft += btn.id === "left" ? -firstCardWidth : firstCardWidth;
setTimeout(updateDots, 50);
});
});
const dragStart = (e) => {
isDragging = true;
carousel.classList.add("dragging");
startX = e.pageX || e.touches[0].pageX;
startScrollLeft = carousel.scrollLeft;
}
const dragging = (e) => {
if(!isDragging) return;
const pageX = e.pageX || e.touches[0].pageX;
carousel.scrollLeft = startScrollLeft - (pageX - startX);
}
const dragStop = () => {
isDragging = false;
carousel.classList.remove("dragging");
}
const infiniteScroll = () => {
if(carousel.scrollLeft === 0) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.scrollWidth - (2 * carousel.offsetWidth);
...