Swiper - National Design System

A horizontal slider for hero banners, image galleries, and multi-card decks, with responsive slides-per-view, optional peek previews, and lazy-loaded images.

Hero Slider

Full-bleed hero carousel showing one slide at a time. Use this when each slide is a marketing message, banner, or call to action that should fill the hero area.

Welcome to Our Platform

Discover innovative solutions for your digital needs

<div class="nds-swiper nds-hero nds-oncolor"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <div class="slide-content" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 400px; display: flex; align-items: center; justify-content: center; padding: 2rem; border-radius: 8px;"> <div style="max-width: 800px; text-align: center;"> <h2 style="color: white; font-size: 2.5rem; font-weight: var(--font-weight-bold); margin-bottom: 1rem;">Welcome to Our Platform</h2> <p style="color: white; font-size: 1.25rem; margin-bottom: 2rem; opacity: 0.95;">Discover innovative solutions for your digital needs</p> <button class="nds-btn nds-primary nds-lg nds-oncolor"> <span class="nds-label">Get Started</span> </button> </div> </div> </div> <div class="nds-swiper-slide" hidden> <div class="slide-content" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); min-height: 400px; display: flex; align-items: center; justify-content: center; padding: 2rem; border-radius: 8px;"> <div style="max-width: 800px; text-align: center;"> <h2 style="color: white; font-size: 2.5rem; font-weight: var(--font-weight-bold); margin-bottom: 1rem;">Powerful Features</h2> <p style="color: white; font-size: 1.25rem; margin-bottom: 2rem; opacity: 0.95;">Built with the latest technology and best practices</p> <button class="nds-btn nds-primary nds-lg nds-oncolor"> <span class="nds-label">Learn More</span> </button> </div> </div> </div> <div class="nds-swiper-slide" hidden> <div class="slide-content" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); min-height: 400px; display: flex; align-items: center; justify-content: center; padding: 2rem; border-radius: 8px;"> <div style="max-width: 800px; text-align: center;"> <h2 style="color: white; font-size: 2.5rem; font-weight: var(--font-weight-bold); margin-bottom: 1rem;">Start Your Journey</h2> <p style="color: white; font-size: 1.25rem; margin-bottom: 2rem; opacity: 0.95;">Join thousands of satisfied users today</p> <button class="nds-btn nds-primary nds-lg nds-oncolor"> <span class="nds-label">Join Now</span> </button> </div> </div> </div> </div> <div class="nds-swiper-navigation" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-subtle nds-icon-only nds-prev" aria-label="Previous slide"></button> <button class="nds-btn nds-subtle nds-icon-only nds-next" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination"></div> </div> </div>

Hero with Images

Hero slider where each slide is a full-bleed image. Pick this when the imagery itself carries the message: photo galleries, campaign banners, or visual storytelling at the top of a page.

Landscape 1
<div class="nds-swiper nds-hero nds-oncolor"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <img data-src="https://picsum.photos/id/1015/800/450" alt="Landscape 1" style="width: 100%; height: 450px; object-fit: cover; border-radius: 8px;"> </div> <div class="nds-swiper-slide" hidden> <img data-src="https://picsum.photos/id/1018/800/450" alt="Landscape 2" style="width: 100%; height: 450px; object-fit: cover; border-radius: 8px;"> </div> <div class="nds-swiper-slide" hidden> <img data-src="https://picsum.photos/id/1039/800/450" alt="Landscape 3" style="width: 100%; height: 450px; object-fit: cover; border-radius: 8px;"> </div> <div class="nds-swiper-slide" hidden> <img data-src="https://picsum.photos/id/1043/800/450" alt="Landscape 4" style="width: 100%; height: 450px; object-fit: cover; border-radius: 8px;"> </div> <div class="nds-swiper-slide" hidden> <img data-src="https://picsum.photos/id/870/800/450" alt="Landscape 5" style="width: 100%; height: 450px; object-fit: cover; border-radius: 8px;"> </div> </div> <div class="nds-swiper-navigation" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-subtle nds-icon-only nds-prev" aria-label="Previous slide"></button> <button class="nds-btn nds-subtle nds-icon-only nds-next" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination"></div> </div> </div>

Deck Beta

A hero with a deck of cards beside the slides, one card per slide. The active card is at the front, the other cards fan behind it, and the front card slides back into the pile when the next one comes forward. A tap on a card goes to its slide; below the desktop breakpoint a drag across the deck follows the finger and pages on release. Below the desktop breakpoint the deck stacks above the text: the open card is centred, its two neighbours peek at the sides. Use it when every slide has its own artwork and the set is worth showing at once, as in a campaign hero.

Mountains

The first card is open; the rest wait as strips.

<div class="nds-swiper nds-hero nds-oncolor nds-deck" style="--total: 5"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <div class="nds-section-body"> <h2 class="nds-section-title">Mountains</h2> <p class="nds-section-description">…</p> </div> </div> <div class="nds-swiper-slide" hidden>…</div> <!-- one slide per card, same order --> </div> <div class="nds-swiper-deck"> <button type="button" class="nds-swiper-card" aria-label="Go to slide 1: Mountains"> <img src="card-1.webp" alt="" fetchpriority="high"> </button> <button type="button" class="nds-swiper-card" aria-label="Go to slide 2: Lake"> <img src="card-2.webp" alt="" loading="lazy"> </button> <!-- … --> </div> <div class="nds-swiper-navigation nds-center" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-subtle nds-icon-only nds-prev" aria-label="Previous slide"></button> <button class="nds-btn nds-subtle nds-icon-only nds-next" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination nds-md"></div> </div> </div>
  • The cards map to the slides by order. Write them in that order and the deck places them itself, before the script runs and from init on. The first card is the open one.
  • Card images fill the card, which is square unless --deck-ratio says otherwise. Give the first one fetchpriority="high" and the rest loading="lazy".
  • A deck loops by default, the same way data-swiper-loop does: the fan wraps, so the track wraps with it. Each loop clone carries data-swiper-clone with its real slide's index, for content you update at runtime.
  • --deck-card is the open card's width in every layout, and --deck-ratio is its shape. Set neither and a card is a 300px square — or, in a page hero's fan layout, as tall as the hero.
  • Inside a page hero the fan fills the hero's height. Below the desktop breakpoint the deck stacks above the text and the hero grows to fit it; the deck does that itself, so the section needs nothing.
  • Add nds-stacked to keep the stacked layout at every width. Use the Stacked button above to see it.
  • The swiper fires nds:swiper:change on every move. Listen to it to change anything outside the swiper with the slide, such as the section background.

Responsive Multi-Slide

Display multiple slides at once with responsive breakpoints: 4 slides on large desktop, 3 on desktop, and 1 on mobile/tablet.

Card 1

Multi-slide example with responsive breakpoints.

Card 2

Resize the browser to see responsive behavior.

Card 3

Drag or use arrows to navigate.

Card 4

Native scroll-snap behavior.

Card 5

Full RTL/LTR support.

Card 6

Touch and keyboard navigation.

<div class="nds-swiper" style="--max-slides:4; --mid-slides:3; --min-slides:1"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 1</span> <p class="nds-card-description">Multi-slide example with responsive breakpoints.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 2</span> <p class="nds-card-description">Resize the browser to see responsive behavior.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 3</span> <p class="nds-card-description">Drag or use arrows to navigate.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 4</span> <p class="nds-card-description">Native scroll-snap behavior.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 5</span> <p class="nds-card-description">Full RTL/LTR support.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 6</span> <p class="nds-card-description">Touch and keyboard navigation.</p> </div> </div> </div> </div> <div class="nds-swiper-navigation" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-prev" type="button" aria-label="Previous slide"></button> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-next" type="button" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination"></div> </div> </div>

Peek Mode

Show part of the next slide to indicate more content. Set --peek to the length left showing.

Card 1

Peek mode shows partial adjacent slides.

Card 2

Users can see there's more content.

Card 3

This encourages scrolling/navigation.

Card 4

Configurable peek amount in pixels.

Card 5

Works with any slides-per-view.

Card 6

Last slide in the carousel.

<div class="nds-swiper" style="--max-slides:3; --mid-slides:2; --min-slides:1; --peek:40px"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 1</span> <p class="nds-card-description">Peek mode shows partial adjacent slides.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 2</span> <p class="nds-card-description">Users can see there's more content.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 3</span> <p class="nds-card-description">This encourages scrolling/navigation.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 4</span> <p class="nds-card-description">Configurable peek amount in pixels.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 5</span> <p class="nds-card-description">Works with any slides-per-view.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 6</span> <p class="nds-card-description">Last slide in the carousel.</p> </div> </div> </div> </div> <div class="nds-swiper-navigation" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-prev" type="button" aria-label="Previous slide"></button> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-next" type="button" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination"></div> </div> </div>

Loop

An endless row. The last slide is followed by the first, in both directions. Add data-swiper-loop to the swiper.

Card 1

Loops back to the first card.

Card 2

Drag or use the arrows.

Card 3

Native scroll snap.

Card 4

RTL and LTR.

Card 5

Keyboard and touch.

Card 6

The last card, then the first again.

<div class="nds-swiper" data-swiper-loop style="--max-slides:3; --mid-slides:2; --min-slides:1; --peek:40px"> <div class="nds-swiper-wrapper"> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 1</span> <p class="nds-card-description">Loops back to the first card.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 2</span> <p class="nds-card-description">Drag or use the arrows.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 3</span> <p class="nds-card-description">Native scroll snap.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 4</span> <p class="nds-card-description">RTL and LTR.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 5</span> <p class="nds-card-description">Keyboard and touch.</p> </div> </div> </div> <div class="nds-swiper-slide"> <div class="nds-card nds-stroke nds-shadow"> <div class="nds-card-content"> <span class="nds-card-title">Card 6</span> <p class="nds-card-description">The last card, then the first again.</p> </div> </div> </div> </div> <div class="nds-swiper-navigation" hidden> <div class="nds-swiper-buttons"> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-prev" type="button" aria-label="Previous slide"></button> <button class="nds-btn nds-primary nds-icon-only nds-circle nds-md nds-next" type="button" aria-label="Next slide"></button> </div> <div class="nds-swiper-pagination"></div> </div> </div>

Built-in Features

Auto-initialization

Every nds-swiper on the page initializes automatically on load with no setup code required.

Native Scroll-Snap

Slides snap into place using CSS scroll-snap, giving smooth drag-to-scroll on desktop and natural swipe gestures on touch devices.

Responsive Breakpoints

Three-tier slide counts (--max-slides, --mid-slides, --min-slides) adjust the visible slides at 960px and 600px breakpoints. CSS reads them, so the row is the right size before any JS runs.

Lazy Loading

Images with data-src or data-srcset load automatically as slides approach the viewport, reducing initial page weight. The image box shimmers until its source lands, so give the image a size.

RTL and LTR

The row, the arrows and the arrow keys follow the page direction. Nothing to set.

Keyboard Navigation

Arrow keys navigate between slides, Home jumps to the first, and End to the last. All keys are direction-aware for RTL layouts.

Peek Preview

Set --peek to a length to reveal part of the next slide, which signals that more content is available.

Endless Loop

Add data-swiper-loop and the row never ends. Clones at both ends make the wrap invisible. Needs more slides than the largest slides-per-view count.

Lazy Slide Reveal

Hero slides marked with hidden are revealed automatically on first visibility, deferring image decoding for off-screen slides until the carousel scrolls into view.

Programmatic Control

Access any swiper instance via element._ndsSwiper to call slideTo(), prev(), next(), or destroy().

Usage Guidelines

Best Practices

  • Use the swiper for horizontally browsable collections like featured services, image galleries, or card carousels where showing everything at once would overwhelm the layout
  • Use the hero variant (nds-hero) for full-width banner sliders with background images or gradient slides at the top of a page
  • Use data-src and data-srcset for lazy loading images rather than standard src to reduce initial page weight. Give each lazy image a width and height, or an aspect ratio, so its box can shimmer before the source lands
  • Do not use swiper for content that should be visible all at once. Use Grid for static card layouts or Tabs for switchable content panels
  • Do not place interactive form controls inside slides. Keep slide content to display elements: text, images, cards, and links
  • Add --peek:40px when the slide count exceeds the visible slots. It gives the reader a visual cue that more content is available
  • Use data-swiper-loop only when the deck has more slides than the largest slides-per-view count. With fewer, the attribute is ignored
  • Always include hidden on .nds-swiper-navigation: the navigation row ships hidden and JS reveals it only when there are multiple pages. The swiper container itself does not use hidden; a CSS ::after placeholder on .nds-swiper:not([data-nds-swiper-initialized]) reserves the navigation row height before init
  • Keep slide heights consistent within a swiper. Mix uneven heights and the tallest slide will define the row height for all others
  • Use nds-middle for a wide strip the reader scans rather than reads, such as a partner or logo row, where arrows beside the slides suit the shape better than a row underneath. It applies from 600px up, so add nds-center to the navigation row as well and the mobile fallback keeps the same left-dots-right arrangement
  • The nds-middle arrows sit over the left and right edges of the slide. Use it for textless slides, or keep the slide text centred so the arrows stay clear of the words. Slide text that runs to the edges will be crossed
  • Always include aria-label on navigation buttons with clear directional text like "Previous slide" and "Next slide"
  • For full-width section breakouts, place the swiper inside a nds-section-body nds-max-width container so it can span beyond the content padding

Modifier Classes

ClassApplied toDescription
nds-hero.nds-swiperFull-width single-slide hero mode with overlay navigation absolutely positioned at the bottom
nds-oncolor.nds-swiperAdjusts the bullets, the section title and the arrows for dark or image backgrounds. The arrows take the subtle on-color wash. A primary or neutral arrow still adds nds-oncolor on the button itself
nds-center.nds-swiper-navigationCenters the bullets and pushes the prev/next buttons to the outer edges of the navigation row
nds-middle.nds-swiperMoves the prev/next buttons out of the navigation row to flank the slides at their vertical centre, and hides the bullets. The swiper gains an inline gutter one button wide at each end, so the arrows sit beside the slides rather than over them. Tablet and up only (600px): below that every rule drops and the normal navigation row returns, bullets included, so pair it with nds-center on the row to choose the mobile arrangement. On nds-hero it adapts: no gutter is reserved, since the hero is full-bleed and insetting the image would be wrong, so the arrows overlay the slide at the viewport padding, and the bullets stay pinned bottom-centre. The arrows then sit over the slide edges, so use this with textless slides, or centre the slide text to keep it clear of them
nds-deck.nds-swiperDeck mode. A .nds-swiper-deck of .nds-swiper-card buttons, one per slide in slide order, sits beside the track. The active card is at the front, the rest fan behind it in circular order; a tap goes to a card, a drag pages below the desktop breakpoint, and the track loops. Write the cards in slide order and nothing else: the deck places them before the script runs and the swiper owns them from init. In a hero the deck fills the hero's height at the inline-end edge; below the desktop breakpoint it stacks above the text with the two neighbours peeking, and the hero grows to fit it. See the Deck demo
nds-stacked.nds-swiper.nds-deckKeeps the stacked deck layout at every width, not only below the desktop breakpoint. The deck sits above the track, the open card is centred, its two neighbours peek at the sides, and a drag pages the deck on desktop too. Use it when the fan beside the track is too wide for the space. In a hero the section grows to fit the deck at every width, not only below desktop. Toggle it in the Deck demo
nds-lg.nds-swiper-paginationLarge pagination bullets (16px). Default size when no modifier is applied
nds-md.nds-swiper-paginationMedium pagination bullets (12px)
nds-sm.nds-swiper-paginationSmall pagination bullets (8px)
nds-loading.nds-swiperShows every card in the deck as a skeleton, the same bars a loading grid shows. Add it while data loads and remove it when the cards are ready

Data Attributes

AttributeDescription
data-swiper-loopSet on .nds-swiper for an endless row. The component clones two pages of slides at each end and jumps silently to the real slide when a scroll rests on a clone. Clones carry nds-swiper-clone, aria-hidden and inert. Ignored when the deck has no more slides than the largest slides-per-view count. Each arrow press moves one full view. When the slide count is not a multiple of the slides per view, every wrap shifts the pages by the remainder, so the bullets can skip the last one at a wrap. While looping, data-state carries no at-start or at-end token
hiddenPlace on .nds-swiper-navigation (not the container). JS re-decides visibility on every breakpoint change: removes hidden when there are multiple pages, restores it when there is only one
data-nds-swiper-initializedSet by JS after init completes (true). Used as a CSS hook (the pre-init ::after height reservation is scoped to :not([data-nds-swiper-initialized])) and as a guard to skip already-initialized swipers during NDS.Swiper.init(). Removed by destroy()
data-swiper-peekToggled on .nds-swiper by JS when peek is active (peek > 0 and more than one page). Before JS runs, CSS reserves the peek from --peek alone. JS then counts the pages, at the loader preset and again at init. A deck left without this attribute gets a zero reserve, so a deck that fits one page shows no dead space at its end. Removed by destroy()
data-swiper-presetSet by the loader before the reveal on every card swiper that has not initialized yet, after it writes --slides and the peek state from --max-slides, --mid-slides, --min-slides and --peek. The skeleton row then shows the same slides per view that init will use, so init moves nothing. Removed by destroy().
data-swiper-singleSet by the loader with data-swiper-preset when the slides fit one page at the current breakpoint (the same page count init uses). Drops the pre-init ::after nav reservation before the reveal, because init keeps the nav hidden on a single page and the row would otherwise vanish at init. Removed by destroy().

CSS Custom Properties

Set these on .nds-swiper (or .nds-bullet) to override the defaults. Resolved tokens like --swiper-gap, --swiper-peek, --swiper-slides, and --swiper-total are managed by the component and should not be set directly.

PropertyDefaultDescription
--max-slides1Slides per view at the large breakpoint (viewport 960px and wider). Set it inline on .nds-swiper so JS can read it too. CSS sizes the row from it the moment the main CSS applies, before any JS, in every browser
--mid-slides1Slides per view at the medium breakpoint (600px to 959px)
--min-slides1Slides per view at the small breakpoint (narrower than 600px)
--total1Number of slides. Set it inline for the first paint, before the script runs — deck mode reads it to size the fan, so a deck without it draws one card wide and clips the rest. The swiper writes the real count at init, so it only matters for what the reader sees first
--peekunsetLength of the next slide left showing at the end of each page, for example 40px. Leave it unset, or set 0px, for no peek. JS drops the reserve when the deck fits one page
--gapvar(--spacing-xl)Gap between slides. Inside .nds-max-width the gutter at each end of the track is one gap too, so a neighbour ends at the edge of the track
--padding0pxGutter at each end of the track. Inside .nds-max-width the default is one gap, and the track runs to the edge of the breakout. Keep it at or below the gap. A wider gutter shows the neighbour slides in it
--swiper-bullet-defaultvar(--colors-neutral-200)Inactive pagination bullet color (light theme); shifts to neutral-700 in dark mode and to translucent white on hero/on-color backgrounds
--swiper-bullet-default-hoveredvar(--colors-neutral-300)Inactive bullet hover color (one step from default: neutral-300 light, neutral-600 dark)
--swiper-bullet-activevar(--colors-primary-600)Active pagination bullet color (light theme); shifts to --colors-primary-500 in dark mode and to base white on hero/on-color backgrounds
--swiper-bullet-active-hoveredvar(--colors-primary-700)Active bullet hover color (one step darker: --colors-primary-700 light, --colors-primary-600 dark)
--swiper-bullet-bordertransparentBorder color around the pagination bullets
--deck-card300pxDeck mode: the open card's width, in every layout — the one knob that sizes a card. Its height follows from --deck-ratio. Set it inline on .nds-swiper. Inside a page hero's fan layout the default is the hero's height instead, so the card fills the hero. In the stacked layout the deck stays fluid: this is the widest the card grows to, and a narrow screen shrinks it to fit
--deck-stripvar(--spacing-5xl)Deck mode: width of a folded card. The fan layout only — the stacked layout has no folded cards, so it ignores this knob
--deck-ratio1Deck mode: the shape of a card, as a plain number for width ÷ height. 1 is a square, above 1 is landscape, below 1 is portrait. --deck-card is always the card's width, so the height follows from this. Write a number, not a fraction: use 1.777, not 16/9
--deck-step0.918Stacked layout: how far a neighbour sits from the open card, as a share of the card's width. 1 puts their edges together, below 1 overlaps them, above 1 pushes them apart
--deck-scale0.73Stacked layout: how large a neighbour is next to the open card, as a number from 0 to 1. 1 makes every card the same size

The bare attributes slides-max, slides-mid, slides-min and peek still work but are deprecated. Only JS can read them, so a row authored that way keeps its old size until the loader preset runs. Use the inline properties above.

JavaScript API

All nds-swiper elements initialize automatically. Access an instance via element._ndsSwiper.

// ── Access instance ── const swiper = document.querySelector('.nds-swiper')._ndsSwiper; // ── Navigation ── swiper.slideTo(2); // Scroll to slide at index 2 (animated) swiper.slideTo(0, false); // Jump to first slide (no animation) swiper.goTo(4); // Snap to a page-aligned index (clamped to bounds) swiper.prev(); // Go to previous page swiper.next(); // Go to next page // Loop decks: indices count real slides only. Clones are never addressed. // ── Boundary state (for CSS hooks) ── // The container exposes data-state as the user scrolls: // data-state="at-start" first page is showing // data-state="at-end" last page is showing // data-state="at-start at-end" only one page (no scroll possible) // (a looping swiper sets neither token) // Style with: .nds-swiper[data-state~="at-end"] { ... } // ── Events ── // nds:swiper:change bubbles from the container after every move. el.addEventListener('nds:swiper:change', (e) => { console.log('slide', e.detail.index); // real slide index, clones never counted }); // ── Cleanup ── swiper.destroy(); // Remove listeners, pagination, and reset state NDS.Swiper.destroy(el); // The same teardown from the namespace. NDS.Init.destroy() // calls this for every swiper in a container it releases. // ── Factory ── const el = document.querySelector('.my-swiper'); const instance = NDS.Swiper.create(el); // Create and initialize a new instance // ── Re-initialize all swipers ── NDS.Swiper.init(); // Finds and initializes all uninitialized .nds-swiper elements NDS.Swiper.reinit(); // Alias for init(), same function, provided for lifecycle symmetry
Last Modified Date: 20/09/2026 - 11:19 AM
Was this page useful?
60% of users said Yes from 2843 Feedbacks