Author: | toprakdeviren |
---|---|
Views Total: | 0 views |
Official Page: | Go to website |
Last Update: | May 22, 2025 |
License: | MIT |
Preview:

Description:
NovaSlider is a lightweight product carousel that turns a static product list into an interactive, touch-enabled, and fully accessible slider.
It can be useful for e-commerce sites needing to feature products, but I can see it working well for portfolio items, testimonials, or any collection of cards you want to present in a compact way.
More Features:
- Pure Vanilla JavaScript: No jQuery, no frameworks. Just ES6+ JS.
- CSS-Driven Animations: Utilizes modern CSS for smooth transitions.
- Responsive: Adapts to different screen sizes out of the box.
- Lazy Loading: Defers image loading to improve initial page speed.
- Customizable Data Structure: Adapts to your product data.
- Interactive Cards: Supports clickable cards and action buttons within them.
- Visual Feedback: Includes loading states, progress bar, and pagination.
How to use it:
1. The required HTML structure for the product carousel.
<main class="carousel-container" id="productCarousel" role="region" aria-labelledby="carouselHeading"> <h2 id="carouselHeading" class="visually-hidden">Featured Products Showcase - NovaSlider</h2> <div class="loading-overlay" aria-hidden="true"> <div class="loader" role="status" aria-label="Loading featured products..."></div> </div> <div class="cards-wrapper" aria-live="polite"></div> <button type="button" class="nav-arrow prev-arrow" aria-label="Previous Product Set" aria-controls="productCarousel"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" focusable="false" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" /> </svg> </button> <button type="button" class="nav-arrow next-arrow" aria-label="Next Product Set" aria-controls="productCarousel"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" focusable="false" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /> </svg> </button> <div class="pagination-dots" role="tablist" aria-label="Product Set Navigation"></div> <div class="progress-container" aria-hidden="true"> <div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-label="Carousel Progress"></div> </div> <div class="keyboard-hint" aria-hidden="true"> Use <kbd class="key" title="Left Arrow Key"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" focusable="false" aria-hidden="true"> <path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" /> </svg> </kbd> and <kbd class="key" title="Right Arrow Key"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" focusable="false" aria-hidden="true"> <path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" /> </svg> </kbd> to navigate </div> </main> <div id="notification-anchor" aria-live="assertive" aria-atomic="true" style="position: fixed; z-index: 9999; bottom: 0; left: 0; width: 100%; display: flex; flex-direction: column; align-items: center; pointer-events: none;"></div>
2. Add the required JavaScript and CSS files to the page.
<link rel=”stylesheet” href=”card.css”>
<script src=”card.js” defer></script>
3. The Carousel is populated from a JavaScript array called PRODUCTS_DATA
inside card.js
. You’ll want to replace this with your own data. If your data schema is different, you’ll need to adjust the createProductCard
function (or similar) within card.js
that maps these properties to the card’s HTML.
const PRODUCTS_DATA = [ { id: 1, imageSrc: 'https://picsum.photos/id/3/600/400', name: 'PURSHE Mini Projector, Portable HD Display for Home Cinema & Outdoor Movies', rating: 4.3, reviews: 61, sku: 'BOCRYVL494', price: '$41.32', category: { name: 'Electronics', class: 'electronics', iconSvg: ICONS.tv }, featured: false, actionButtons: [{label: ICONS.heart, aria: 'Add to favorites'}, {label: ICONS.eye, aria: 'View details'}] }, { id: 2, imageSrc: 'https://picsum.photos/id/96/600/400', name: 'XBOX Wireless Controller - Electric Volt Special Edition with Textured Grips', rating: 4.8, reviews: 1205, sku: 'GAMEXCTRL01', price: '$59.99', category: { name: 'Gaming', class: 'gaming', iconSvg: ICONS.gamepad }, featured: true, actionButtons: [{label: ICONS.heart, aria: 'Add to favorites'}, {label: ICONS.eye, aria: 'View details'}] }, { id: 3, imageSrc: 'https://picsum.photos/id/250/600/400', name: 'Polaroid Now i-Type Instant Camera - Retro Blue Design, Autofocus', rating: 4.5, reviews: 350, sku: 'POLAROIDNOW', price: '$99.99', category: { name: 'Photography', class: 'photo', iconSvg: ICONS.camera }, featured: false, actionButtons: [{label: ICONS.heart, aria: 'Add to favorites'}, {label: ICONS.eye, aria: 'View details'}] }, { id: 4, imageSrc: 'https://picsum.photos/id/160/600/400', name: 'FitVerse Smart Watch Pro - Advanced Health & Fitness Tracker with GPS', rating: 4.6, reviews: 890, sku: 'SMTWCHPROX', price: '$129.50', category: { name: 'Wearables', class: 'wearables', iconSvg: ICONS.watch }, featured: false, actionButtons: [{label: ICONS.heart, aria: 'Add to favorites'}, {label: ICONS.eye, aria: 'View details'}] }, { id: 5, imageSrc: 'https://picsum.photos/id/127/600/400', name: 'AuraSound Noise Cancelling Over-Ear Headphones - Onyx Black, Hi-Fi Audio', rating: 4.9, reviews: 2100, sku: 'AURAHDP005', price: '$199.00', category: { name: 'Audio', class: 'audio', iconSvg: ICONS.headphones }, featured: true, actionButtons: [{label: ICONS.heart, aria: 'Add to favorites'}, {label: ICONS.eye, aria: 'View details'}] } ];
4. At the top of card.js
, there’s a CONFIG
object. This is where you can tweak some behaviors:
const CONFIG = { animationDuration: 300, swipeThreshold: 50, touchMovementScaleFactor: 0.6, initialLoadDelay: 600, notificationTimeout: 3500, debounceResizeTime: 150 };
5. Customize the carousel by overriding the default CSS variables in the card.css
.
:root { --color-surface-primary: #ffffff; --color-surface-secondary: #f9faff; --color-surface-accent: #f0f6ff; --color-surface-overlay: rgba(240, 246, 255, 0.65); --color-text-primary: #1a202c; --color-text-secondary: #4a5568; --color-text-tertiary: #718096; --color-text-on-accent: #ffffff; --color-accent-primary: #0052cc; --color-accent-primary-hover: #0041a3; --color-accent-primary-darker: #003380; --color-accent-secondary: #e6f0ff; --color-accent-primary-rgb: 0, 82, 204; --color-surface-accent-rgb: 240, 246, 255; --color-rating: #ffb400; --color-success: #34c759; --color-featured-badge-bg-start: #ffdd57; --color-featured-badge-bg-end: #ffb400; --color-featured-badge-text: #4a3b00; --color-featured-badge-icon: #9e7300; --color-border-light: rgba(0, 27, 71, 0.1); --color-border-focus: rgba(0, 102, 255, 0.6); --color-border-interactive: rgba(0, 27, 71, 0.25); --category-electronics-bg: #e0e7ff; --category-electronics-text: #3730a3; --category-gaming-bg: #dcfce7; --category-gaming-text: #15803d; --category-photo-bg: #fffbeb; --category-photo-text: #b45309; --category-wearables-bg: #dbeafe; --category-wearables-text: #1d4ed8; --category-audio-bg: #fee2e2; --category-audio-text: #b91c1c; --shadow-xs: 0 1px 2px rgba(26, 32, 44, 0.03); --shadow-sm: 0 2px 4px rgba(26, 32, 44, 0.05); --shadow-md: 0 6px 16px rgba(26, 32, 44, 0.07); --shadow-lg: 0 12px 32px rgba(26, 32, 44, 0.09); --shadow-xl: 0 24px 48px rgba(26, 32, 44, 0.1), 0 8px 16px rgba(26,32,44,0.06); --shadow-focus-ring: 0 0 0 3px var(--color-border-focus); --shadow-inset-light: inset 0 1px 2px rgba(0,0,0,0.06); --shadow-inset-active: inset 0 2px 4px rgba(0,0,0,0.08); --duration-micro: 100ms; --duration-fast: 200ms; --duration-normal: 350ms; --duration-slow: 500ms; --duration-extra-slow: 900ms; --timing-ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94); --timing-ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); --timing-ease-in-out-cubic: cubic-bezier(0.65, 0, 0.35, 1); --timing-soft-eio: cubic-bezier(0.76, 0, 0.24, 1); --timing-anticipate: cubic-bezier(0.38, -0.2, 0.36, 1.4); --timing-spring: cubic-bezier(0.34, 1.56, 0.64, 1); --timing-elegant-snap: cubic-bezier(0.25, 0.1, 0.2, 1.25); --font-family-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --font-size-xs: 0.75rem; --font-size-sm: 0.875rem; --font-size-md: 1rem; --font-size-lg: 1.125rem; --font-size-xl: 1.375rem; --line-height-tight: 1.25; --line-height-normal: 1.5; --line-height-relaxed: 1.75; --letter-spacing-tight: -0.02em; --letter-spacing-normal: 0; --letter-spacing-wide: 0.025em; --spacing-unit: 4px; --space-xs: calc(var(--spacing-unit) * 1); --space-sm: calc(var(--spacing-unit) * 2); --space-md: calc(var(--spacing-unit) * 4); --space-lg: calc(var(--spacing-unit) * 6); --space-xl: calc(var(--spacing-unit) * 8); --radius-sm: 6px; --radius-md: 10px; --radius-lg: 16px; --radius-xl: 20px; --radius-full: 9999px; --card-min-width: 280px; --card-max-width: 320px; --card-height: 510px; --card-padding: var(--space-lg); --card-margin-inline: var(--space-md); --card-scale-inactive: 0.92; --card-y-offset-inactive: 0px; --card-opacity-inactive: 0.7; --card-blur-inactive: 0.8px; --card-saturate-inactive: 0.9; --card-scale-active: 1.035; --card-y-offset-active: -12px; --card-active-border-width: 2.5px; --carousel-perspective: 2000px; --carousel-arrow-size: 44px; --carousel-arrow-offset: calc(var(--carousel-arrow-size) / -2.2); --focus-outline-offset: 2px; }