Travel Adventures Slider Template
Preview
Edit
Download
Run
Download Options
HTML File
Download as .html file
CSS File
Download as .css file
JavaScript File
Download as .js file
Combined HTML
All code in one HTML file
Project ZIP
All files in a ZIP archive
Cancel
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Family Travel Adventures | Animated Slider</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet"> </head> <body> <!-- Background decorative elements --> <div class="bg-element bg-1"><i class="fas fa-globe-americas"></i></div> <div class="bg-element bg-2"><i class="fas fa-mountain"></i></div> <div class="bg-element bg-3"><i class="fas fa-umbrella-beach"></i></div> <div class="bg-element bg-4"><i class="fas fa-campground"></i></div> <div class="container"> <header> <h1>Family Travel Adventures</h1> <p class="subtitle">Discover incredible destinations tailored for families. Create lasting memories with activities for all ages.</p> <div class="tagline"> <i class="fas fa-heart"></i> <span>Handpicked destinations for unforgettable family moments</span> <i class="fas fa-heart"></i> </div> </header> <div class="slider-wrapper"> <div class="slider-container"> <div class="slider" id="slider"> <!-- Cards will be generated by JavaScript --> </div> </div> <div class="slider-controls"> <button class="slider-btn" id="prevBtn"> <i class="fas fa-chevron-left"></i> </button> <div class="slider-dots" id="sliderDots"> <!-- Dots will be generated by JavaScript --> </div> <button class="slider-btn" id="nextBtn"> <i class="fas fa-chevron-right"></i> </button> </div> <div class="card-counter"> <span>Destination</span> <span class="counter-highlight" id="currentCard">1</span> <span>of</span> <span class="counter-highlight" id="totalCards">12</span> </div> <div class="auto-play-toggle" id="autoPlayToggle"> <span>Auto-play</span> <div class="toggle-switch"></div> </div> </div> <footer> <p>© 2023 <span class="footer-highlight">Family Travel Adventures</span>. All destinations include family-friendly accommodations, activities, and 24/7 support.</p> <p><i class="fas fa-star"></i> Rated #1 in family travel experiences by TravelWithKids Magazine <i class="fas fa-star"></i></p> </footer> </div> </body> </html>
CSS
* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Nunito', sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%); color: #333; line-height: 1.6; min-height: 100vh; padding: 20px; overflow-x: hidden; } .container { max-width: 1400px; margin: 0 auto; padding: 20px; } header { text-align: center; margin-bottom: 50px; animation: fadeInDown 1s ease-out; } h1 { font-family: 'Poppins', sans-serif; color: #2c3e50; font-size: 3.2rem; margin-bottom: 15px; background: linear-gradient(90deg, #3498db, #2ecc71, #e74c3c); -webkit-background-clip: text; background-clip: text; color: transparent; display: inline-block; position: relative; } h1:after { content: ''; position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%); width: 120px; height: 4px; background: linear-gradient(90deg, #3498db, #2ecc71); border-radius: 2px; } .subtitle { color: #7f8c8d; font-size: 1.3rem; max-width: 800px; margin: 0 auto 25px; } .tagline { display: flex; justify-content: center; align-items: center; gap: 15px; color: #3498db; font-weight: 600; font-size: 1.1rem; } .tagline i { animation: bounce 2s infinite; } .slider-wrapper { position: relative; padding: 30px 0 80px; overflow: hidden; } .slider-container { position: relative; width: 100%; overflow: visible; } .slider { display: flex; transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1); gap: 30px; padding: 20px 10px; } .card { background: white; border-radius: 24px; box-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07); overflow: hidden; flex: 0 0 calc(100% - 40px); min-width: 0; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); opacity: 0.7; transform: scale(0.9); position: relative; z-index: 1; } .card.active { opacity: 1; transform: scale(1); z-index: 10; box-shadow: 0 25px 50px rgba(50, 50, 93, 0.15), 0 15px 25px rgba(0, 0, 0, 0.1); } .card:hover { transform: translateY(-15px) scale(1.02); box-shadow: 0 30px 60px rgba(50, 50, 93, 0.2), 0 20px 30px rgba(0, 0, 0, 0.15); } .card-corner { position: absolute; top: 0; right: 0; width: 70px; height: 70px; background: linear-gradient(135deg, #3498db, #2ecc71); clip-path: polygon(0 0, 100% 0, 100% 100%); display: flex; justify-content: flex-end; align-items: flex-start; padding: 12px; color: white; font-size: 1.5rem; } .card-image { height: 250px; width: 100%; background-size: cover; background-position: center; position: relative; overflow: hidden; } .card-image:after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 60px; background: linear-gradient(to top, rgba(255,255,255,0.8), transparent); } .destination-badge { position: absolute; bottom: 20px; left: 20px; background: rgba(255, 255, 255, 0.95); padding: 12px 20px; border-radius: 50px; display: flex; align-items: center; gap: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); animation: slideInLeft 0.5s 0.3s both; } .destination-name { font-family: 'Poppins', sans-serif; font-size: 1.8rem; font-weight: 700; color: #2c3e50; } .destination-flag { font-size: 2rem; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.2)); } .card-content { padding: 30px; position: relative; } .duration { display: inline-block; background: linear-gradient(90deg, #3498db, #2ecc71); color: white; padding: 8px 20px; border-radius: 50px; font-weight: 700; font-size: 1rem; margin-bottom: 25px; box-shadow: 0 4px 10px rgba(52, 152, 219, 0.3); animation: pulse 2s infinite; } .activities-title { color: #2c3e50; font-weight: 700; margin-bottom: 15px; font-size: 1.2rem; display: flex; align-items: center; gap: 10px; } .activities-title i { color: #3498db; } .activities-list { list-style-type: none; margin-bottom: 30px; } .activities-list li { padding: 10px 0; border-bottom: 1px dashed #eee; display: flex; align-items: center; transition: transform 0.3s; animation: fadeInUp 0.5s both; } .activities-list li:hover { transform: translateX(10px); } .activities-list li:last-child { border-bottom: none; } .activities-list i { color: #2ecc71; margin-right: 12px; width: 22px; font-size: 1.1rem; } .card-footer { display: flex; justify-content: space-between; align-items: center; padding-top: 20px; border-top: 2px solid #f8f9fa; } .price { font-size: 2.2rem; color: #2c3e50; font-weight: 800; position: relative; } .price span { font-size: 1rem; color: #7f8c8d; font-weight: 500; display: block; } .price:before { content: 'From'; position: absolute; top: -20px; left: 0; font-size: 0.9rem; color: #3498db; font-weight: 600; } .cta-button { background: linear-gradient(90deg, #e74c3c, #f39c12); color: white; border: none; padding: 15px 30px; border-radius: 50px; font-weight: 700; font-size: 1.1rem; cursor: pointer; transition: all 0.3s; display: flex; align-items: center; gap: 10px; box-shadow: 0 5px 15px rgba(231, 76, 60, 0.3); position: relative; overflow: hidden; } .cta-button:before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); transition: left 0.7s; } .cta-button:hover:before { left: 100%; } .cta-button:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(231, 76, 60, 0.4); } .slider-controls { display: flex; justify-content: center; align-items: center; gap: 30px; margin-top: 40px; } .slider-btn { background: white; border: none; width: 60px; height: 60px; border-radius: 50%; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); cursor: pointer; display: flex; justify-content: center; align-items: center; font-size: 1.5rem; color: #3498db; transition: all 0.3s; position: relative; z-index: 10; } .slider-btn:hover { background: #3498db; color: white; transform: scale(1.1); box-shadow: 0 15px 30px rgba(52, 152, 219, 0.3); } .slider-dots { display: flex; gap: 12px; } .dot { width: 14px; height: 14px; border-radius: 50%; background-color: #ddd; cursor: pointer; transition: all 0.3s; position: relative; } .dot.active { background-color: #3498db; transform: scale(1.3); box-shadow: 0 0 10px rgba(52, 152, 219, 0.5); } .dot:after { content: ''; position: absolute; top: -5px; left: -5px; right: -5px; bottom: -5px; border-radius: 50%; border: 2px solid transparent; transition: border-color 0.3s; } .dot.active:after { border-color: rgba(52, 152, 219, 0.2); } .card-counter { text-align: center; color: #7f8c8d; margin-top: 20px; font-weight: 700; font-size: 1.1rem; display: flex; justify-content: center; align-items: center; gap: 10px; } .counter-highlight { background: #2c3e50; color: white; padding: 5px 15px; border-radius: 20px; min-width: 40px; display: inline-block; } .auto-play-toggle { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px; color: #7f8c8d; } .toggle-switch { width: 50px; height: 26px; background: #ccc; border-radius: 13px; position: relative; cursor: pointer; transition: background 0.3s; } .toggle-switch.active { background: #2ecc71; } .toggle-switch:after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; background: white; border-radius: 50%; transition: transform 0.3s; } .toggle-switch.active:after { transform: translateX(24px); } footer { text-align: center; margin-top: 60px; color: #7f8c8d; font-size: 0.95rem; padding: 20px; border-top: 1px solid #eaeaea; animation: fadeIn 1.5s 1s both; } .footer-highlight { color: #3498db; font-weight: 600; } /* Animations */ @keyframes fadeInDown { from { opacity: 0; transform: translateY(-30px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideInLeft { from { opacity: 0; transform: translateX(-30px); } to { opacity: 1; transform: translateX(0); } } @keyframes pulse { 0% { box-shadow: 0 4px 10px rgba(52, 152, 219, 0.3); } 50% { box-shadow: 0 4px 20px rgba(52, 152, 219, 0.5); } 100% { box-shadow: 0 4px 10px rgba(52, 152, 219, 0.3); } } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } } /* Responsive Design */ @media (min-width: 768px) { .card { flex: 0 0 calc(50% - 30px); } } @media (min-width: 1024px) { .card { flex: 0 0 calc(33.333% - 30px); } } @media (min-width: 1400px) { .card { flex: 0 0 calc(25% - 30px); } } @media (max-width: 767px) { h1 { font-size: 2.5rem; } .subtitle { font-size: 1.1rem; } .card-content { padding: 25px; } .destination-name { font-size: 1.6rem; } .slider-btn { width: 50px; height: 50px; } .cta-button { padding: 12px 25px; font-size: 1rem; } } /* Background decorative elements */ .bg-element { position: fixed; z-index: -1; opacity: 0.1; animation: float 15s infinite ease-in-out; } .bg-1 { top: 10%; left: 5%; font-size: 8rem; color: #3498db; } .bg-2 { top: 20%; right: 10%; font-size: 6rem; color: #2ecc71; animation-delay: 2s; } .bg-3 { bottom: 20%; left: 10%; font-size: 7rem; color: #e74c3c; animation-delay: 4s; } .bg-4 { bottom: 10%; right: 5%; font-size: 5rem; color: #f39c12; animation-delay: 6s; }
JavaScript
// Enhanced destination data with 12 cards const destinations = [ { id: 1, name: "Costa Rica", flag: "??", image: "https://images.unsplash.com/photo-1536700503339-1e4b06520771?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "7 Days", price: "$2,499", activities: [ "Rainforest wildlife tours", "Beachside family resorts", "Volcano exploration hikes", "Eco-friendly zip lining" ], cta: "Plan Adventure", cornerIcon: "fas fa-leaf" }, { id: 2, name: "Swiss Alps", flag: "??", image: "https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "10 Days", price: "$3,899", activities: [ "Scenic train rides", "Family skiing lessons", "Chocolate factory tours", "Alpine lake picnics" ], cta: "Book Now", cornerIcon: "fas fa-mountain" }, { id: 3, name: "Japan", flag: "??", image: "https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1194&q=80", duration: "12 Days", price: "$3,299", activities: [ "Interactive museum visits", "Kid-friendly sushi classes", "Theme park adventures", "Cherry blossom viewing" ], cta: "Explore Japan", cornerIcon: "fas fa-torii-gate" }, { id: 4, name: "Australia", flag: "??", image: "https://images.unsplash.com/photo-1506973035872-a4ec16b8e8d9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "14 Days", price: "$4,199", activities: [ "Great Barrier Reef snorkeling", "Kangaroo sanctuary visits", "Family surfing lessons", "Coastal road trips" ], cta: "Discover Down Under", cornerIcon: "fas fa-fish" }, { id: 5, name: "Italy", flag: "??", image: "https://images.unsplash.com/photo-1534447677768-be436bb09401?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1194&q=80", duration: "9 Days", price: "$2,899", activities: [ "Gelato tasting tours", "Ancient ruins exploration", "Pizza making workshops", "Gondola rides in Venice" ], cta: "Experience Italy", cornerIcon: "fas fa-pizza-slice" }, { id: 6, name: "Canada", flag: "??", image: "https://images.unsplash.com/photo-1503614472-8c93d56e92ce?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1111&q=80", duration: "8 Days", price: "$2,199", activities: [ "National park camping", "Whale watching tours", "Maple syrup farm visits", "Lakeside family cabins" ], cta: "Book Canadian Trip", cornerIcon: "fas fa-tree" }, { id: 7, name: "Bali", flag: "??", image: "https://images.unsplash.com/photo-1537953773345-d172ccf13cf1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "10 Days", price: "$2,599", activities: [ "Family yoga sessions", "Water temple visits", "Traditional dance classes", "Beachfront villas" ], cta: "Explore Bali", cornerIcon: "fas fa-spa" }, { id: 8, name: "South Africa", flag: "??", image: "https://images.unsplash.com/photo-1516026672322-bc52d61a55d5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1072&q=80", duration: "11 Days", price: "$3,499", activities: [ "Safari game drives", "Penguin beach visits", "Cape Town cable car", "Cultural village tours" ], cta: "Safari Adventure", cornerIcon: "fas fa-paw" }, { id: 9, name: "Greece", flag: "??", image: "https://images.unsplash.com/photo-1533105079780-92b9be482077?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1074&q=80", duration: "8 Days", price: "$2,799", activities: [ "Island hopping tours", "Mythology museum visits", "Olive farm experiences", "Family sailing trips" ], cta: "Greek Odyssey", cornerIcon: "fas fa-water" }, { id: 10, name: "New Zealand", flag: "??", image: "https://images.unsplash.com/photo-1507699622108-4be3abd695ad?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1171&q=80", duration: "13 Days", price: "$3,999", activities: [ "Hobbiton movie set tour", "Glacier hiking", "Maori cultural shows", "Adventure parks" ], cta: "Kiwi Adventure", cornerIcon: "fas fa-film" }, { id: 11, name: "Iceland", flag: "??", image: "https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "7 Days", price: "$3,299", activities: [ "Northern lights viewing", "Glacier lagoon boat tours", "Geothermal pool visits", "Waterfall exploration" ], cta: "Icelandic Magic", cornerIcon: "fas fa-snowflake" }, { id: 12, name: "Thailand", flag: "??", image: "https://images.unsplash.com/photo-1528181304800-259b08848526?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80", duration: "9 Days", price: "$2,399", activities: [ "Elephant sanctuary visits", "Floating market tours", "Thai cooking classes", "Island beach days" ], cta: "Thai Experience", cornerIcon: "fas fa-utensils" } ]; // DOM Elements const slider = document.getElementById('slider'); const sliderDots = document.getElementById('sliderDots'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const currentCardEl = document.getElementById('currentCard'); const totalCardsEl = document.getElementById('totalCards'); const autoPlayToggle = document.getElementById('autoPlayToggle'); const toggleSwitch = autoPlayToggle.querySelector('.toggle-switch'); // State variables let currentIndex = 0; let cardsPerView = 1; let isDragging = false; let startPos = 0; let currentTranslate = 0; let prevTranslate = 0; let animationID = 0; let autoPlayInterval; let isAutoPlay = true; // Initialize the slider function initSlider() { // Set total cards count totalCardsEl.textContent = destinations.length; // Create cards destinations.forEach((destination, index) => { const card = document.createElement('div'); card.className = `card ${index === 0 ? 'active' : ''}`; card.dataset.index = index; card.innerHTML = ` <div class="card-corner"> <i class="${destination.cornerIcon}"></i> </div> <div class="card-image" style="background-image: url('${destination.image}')"> <div class="destination-badge"> <div class="destination-flag">${destination.flag}</div> <div class="destination-name">${destination.name}</div> </div> </div> <div class="card-content"> <div class="duration">${destination.duration}</div> <div class="activities-title"> <i class="fas fa-child"></i> <span>Family Activities:</span> </div> <ul class="activities-list"> ${destination.activities.map((activity, i) => ` <li style="animation-delay: ${0.1 * i}s"> <i class="fas fa-check-circle"></i> ${activity} </li> `).join('')} </ul> <div class="card-footer"> <div class="price">${destination.price}<span>per family</span></div> <button class="cta-button"> <i class="fas fa-suitcase-rolling"></i> ${destination.cta} </button> </div> </div> `; // Add event listener to CTA button const ctaButton = card.querySelector('.cta-button'); ctaButton.addEventListener('click', () => { showBookingModal(destination); }); slider.appendChild(card); }); // Create dots destinations.forEach((_, index) => { const dot = document.createElement('div'); dot.className = `dot ${index === 0 ? 'active' : ''}`; dot.dataset.index = index; dot.addEventListener('click', () => goToSlide(index)); sliderDots.appendChild(dot); }); // Update cards per view based on screen width updateCardsPerView(); updateSliderPosition(); // Add event listeners for navigation buttons prevBtn.addEventListener('click', goToPrevSlide); nextBtn.addEventListener('click', goToNextSlide); // Add touch/swipe events slider.addEventListener('touchstart', touchStart); slider.addEventListener('touchmove', touchMove); slider.addEventListener('touchend', touchEnd); // Add mouse events for desktop dragging slider.addEventListener('mousedown', mouseDown); slider.addEventListener('mousemove', mouseMove); slider.addEventListener('mouseup', mouseUp); slider.addEventListener('mouseleave', mouseLeave); // Auto-play toggle toggleSwitch.addEventListener('click', toggleAutoPlay); // Update on window resize window.addEventListener('resize', updateCardsPerView); // Start auto-play startAutoPlay(); } // Show booking modal function showBookingModal(destination) { // In a real app, this would open a modal // For this example, we'll show an alert with animation const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; justify-content: center; align-items: center; z-index: 1000; animation: fadeIn 0.3s; `; modal.innerHTML = ` <div style="background: white; padding: 30px; border-radius: 20px; max-width: 500px; width: 90%; animation: fadeInUp 0.5s;"> <h2 style="color: #2c3e50; margin-bottom: 20px; display: flex; align-items: center; gap: 10px;"> ${destination.flag} Plan Your Trip to ${destination.name} </h2> <p style="margin-bottom: 25px; color: #555;">Our family travel experts will contact you within 24 hours to customize this ${destination.duration.toLowerCase()} adventure for your family.</p> <div style="display: flex; justify-content: flex-end; gap: 15px;"> <button id="closeModal" style="padding: 10px 20px; border: 2px solid #ddd; background: white; border-radius: 50px; cursor: pointer; font-weight: 600;">Close</button> <button style="padding: 10px 25px; background: linear-gradient(90deg, #3498db, #2ecc71); color: white; border: none; border-radius: 50px; cursor: pointer; font-weight: 600;">Confirm Booking</button> </div> </div> `; document.body.appendChild(modal); // Close modal on button click or background click modal.querySelector('#closeModal').addEventListener('click', () => { document.body.removeChild(modal); }); modal.addEventListener('click', (e) => { if (e.target === modal) { document.body.removeChild(modal); } }); } // Update cards per view based on screen width function updateCardsPerView() { if (window.innerWidth >= 1400) { cardsPerView = 4; } else if (window.innerWidth >= 1024) { cardsPerView = 3; } else if (window.innerWidth >= 768) { cardsPerView = 2; } else { cardsPerView = 1; } // Update slider position after resize updateSliderPosition(); } // Update slider position function updateSliderPosition() { // Calculate card width including gap const card = document.querySelector('.card'); if (!card) return; const cardStyle = getComputedStyle(card); const cardWidth = card.offsetWidth + 30; // 30px is the gap // Calculate the translate value const translateX = -currentIndex * cardWidth; slider.style.transform = `translateX(${translateX}px)`; // Update active cards updateActiveCards(); // Update dots updateDots(); // Update current card counter currentCardEl.textContent = currentIndex + 1; } // Update active cards function updateActiveCards() { const cards = document.querySelectorAll('.card'); cards.forEach((card, index) => { if (index >= currentIndex && index < currentIndex + cardsPerView) { card.classList.add('active'); } else { card.classList.remove('active'); } }); } // Update active dot function updateDots() { const dots = document.querySelectorAll('.dot'); dots.forEach((dot, index) => { dot.classList.toggle('active', index === currentIndex); }); } // Go to specific slide function goToSlide(index) { // Ensure index is within bounds if (index < 0) { index = 0; } else if (index > destinations.length - cardsPerView) { index = destinations.length - cardsPerView; } currentIndex = index; updateSliderPosition(); } // Go to previous slide function goToPrevSlide() { if (currentIndex > 0) { goToSlide(currentIndex - 1); } } // Go to next slide function goToNextSlide() { if (currentIndex < destinations.length - cardsPerView) { goToSlide(currentIndex + 1); } else { // Loop back to the beginning goToSlide(0); } } // Toggle auto-play function toggleAutoPlay() { isAutoPlay = !isAutoPlay; toggleSwitch.classList.toggle('active', isAutoPlay); if (isAutoPlay) { startAutoPlay(); } else { stopAutoPlay(); } } // Start auto-play function startAutoPlay() { stopAutoPlay(); // Clear any existing interval autoPlayInterval = setInterval(() => { if (currentIndex < destinations.length - cardsPerView) { goToSlide(currentIndex + 1); } else { goToSlide(0); } }, 4000); } // Stop auto-play function stopAutoPlay() { if (autoPlayInterval) { clearInterval(autoPlayInterval); } } // Touch events for mobile swipe function touchStart(event) { isDragging = true; startPos = event.touches[0].clientX; animationID = requestAnimationFrame(animation); slider.style.cursor = 'grabbing'; stopAutoPlay(); } function touchMove(event) { if (!isDragging) return; const currentPosition = event.touches[0].clientX; const diff = currentPosition - startPos; currentTranslate = prevTranslate + diff; } function touchEnd() { if (!isDragging) return; isDragging = false; cancelAnimationFrame(animationID); const movedBy = currentTranslate - prevTranslate; // If moved enough, change slide if (movedBy < -100 && currentIndex < destinations.length - cardsPerView) { goToNextSlide(); } else if (movedBy > 100 && currentIndex > 0) { goToPrevSlide(); } // Reset currentTranslate = 0; prevTranslate = 0; // Update slider position const card = document.querySelector('.card'); const cardWidth = card.offsetWidth + 30; slider.style.transform = `translateX(${-currentIndex * cardWidth}px)`; slider.style.cursor = 'grab'; // Restart auto-play if enabled if (isAutoPlay) { startAutoPlay(); } } // Mouse events for desktop dragging function mouseDown(event) { isDragging = true; startPos = event.clientX; animationID = requestAnimationFrame(animation); slider.style.cursor = 'grabbing'; stopAutoPlay(); event.preventDefault(); } function mouseMove(event) { if (!isDragging) return; const currentPosition = event.clientX; const diff = currentPosition - startPos; currentTranslate = prevTranslate + diff; } function mouseUp() { if (!isDragging) return; isDragging = false; cancelAnimationFrame(animationID); const movedBy = currentTranslate - prevTranslate; // If moved enough, change slide if (movedBy < -100 && currentIndex < destinations.length - cardsPerView) { goToNextSlide(); } else if (movedBy > 100 && currentIndex > 0) { goToPrevSlide(); } // Reset currentTranslate = 0; prevTranslate = 0; // Update slider position const card = document.querySelector('.card'); const cardWidth = card.offsetWidth + 30; slider.style.transform = `translateX(${-currentIndex * cardWidth}px)`; slider.style.cursor = 'grab'; // Restart auto-play if enabled if (isAutoPlay) { startAutoPlay(); } } function mouseLeave() { if (isDragging) { isDragging = false; cancelAnimationFrame(animationID); // Reset currentTranslate = 0; prevTranslate = 0; // Update slider position const card = document.querySelector('.card'); const cardWidth = card.offsetWidth + 30; slider.style.transform = `translateX(${-currentIndex * cardWidth}px)`; slider.style.cursor = 'grab'; // Restart auto-play if enabled if (isAutoPlay) { startAutoPlay(); } } } // Animation for smooth dragging function animation() { setSliderPosition(); if (isDragging) requestAnimationFrame(animation); } function setSliderPosition() { // Calculate card width including gap const card = slider.children[0]; const cardWidth = card.offsetWidth + 30; // Apply the translate value during dragging slider.style.transform = `translateX(${-currentIndex * cardWidth + currentTranslate}px)`; } // Initialize slider when DOM is loaded document.addEventListener('DOMContentLoaded', initSlider);
Output Preview
Desktop
Mobile
Fullscreen