Categories: CSSScriptWeb Design

Responsive, Accessible Product Carousel – NovaSlider

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;
}

The post Responsive, Accessible Product Carousel – NovaSlider appeared first on CSS Script.

rssfeeds-admin

Share
Published by
rssfeeds-admin

Recent Posts

Resident Evil Requiem Producer Sees DLSS 5 AI Backlash as ‘a Positive’ Because ‘It Meant We Got the Design Right’

Resident Evil Requiem producer Masato Kumazawa has said Capcom sees the drama surrounding the DLSS…

25 minutes ago

Isa Briones Blasts ‘Disrespectful’ Fans for Yelling Pitt References During Her Broadway Show

The Pitt star Isa Briones has called out "f**king disrespectful" fans for yelling references while…

26 minutes ago

Pinecone targets agentic completion rates

Pinecone has released Pinecone Nexus, a knowledge engine designed to move reasoning from retrieval to…

40 minutes ago

Five tips to use AI in loyalty and promotions campaigns

Enterprise Times met with Michal Sedzielewski co-founder of Voucherify at the MACH X event in…

40 minutes ago

Using AI to enable automations

Companies embarking on their first investments in Artificial Intelligence-led projects aim to use the new…

41 minutes ago

DOJ Sentences Two Americans to Prison for ALPHV BlackCat Attacks on U.S. Victims

Two American cybersecurity professionals were sentenced to four years each in federal prison on April…

2 hours ago

This website uses cookies.