Swiper

Swiper is a touch-friendly horizontal scroll component. It shares the same responsive max-width system as .container and adds drag-to-scroll behavior powered by the Pointer Events API — no third-party library needed.

Use Swiper for:

  • Product and media card carousels
  • Horizontally scrollable tag or filter rows
  • Image galleries and photo strips
  • News and article feed sliders
  • Step indicators and onboarding flows
  • Any overflowing horizontal list FrontAlign Swiper combines a CSS layout structure with a JavaScript drag engine. The visual layer is provided by .swiper, .swiper-wrapper, and .swiper-item classes, while the JavaScript layer handles pointer events, click guarding, scroll multiplier, and disposal.

Getting Started

Swiper does not need to be initialized manually. FrontAlign's Smart Observer detects .swiper[fa-component] elements in the DOM and activates them automatically.

<div className="swiper" fa-component="swiper">
  <div className="swiper-wrapper">
    <div className="swiper-item w-2fr3 p-4 bg-blue">
      <div className="card">Card 1</div>
    </div>
    <div className="swiper-item w-2fr3 p-4 bg-indigo">
      <div className="card">Card 2</div>
    </div>
    <div className="swiper-item w-2fr3 p-4 bg-success">
      <div className="card">Card 3</div>
    </div>
  </div>
</div>

No additional script is required when the Smart Observer is active — the swiper initializes as soon as the element enters the DOM.

Card 1
Card 2
Card 3

Swiper requires three nested elements: the outer .swiper wrapper, a .swiper-wrapper scroll track, and one or more .swiper-item children.

Elements

.swiper

The outer wrapper. Clips overflowing items with overflow: hidden and shares the container's responsive max-width and margin-inline: auto centering. Receives the .is-dragging class during active drag.

.swiper-wrapper

The horizontal scroll track. Uses display: flex with flex-wrap: nowrap to keep all items on a single row. The native scrollbar is hidden on all browsers for a clean appearance. -webkit-overflow-scrolling: touch enables momentum scrolling on iOS.

.swiper-item

Individual slides or cards. Uses flex: 0 0 auto so items never grow or shrink — they always render at their natural or explicitly defined width. scroll-snap-align: start snaps items to the leading edge during scroll.

If the .swiper-wrapper is not found inside the element, the initializer will not work — it will not throw.

Drag Behavior

Drag is powered by the Pointer Events API, which handles both mouse and touch in a single code path.

Lifecycle

EventWhat happens
pointerdownRecords start position and scrollLeft. Sets pointer capture so drag continues even if cursor leaves the element. Adds .is-dragging to the outer wrapper.
pointermoveCalculates delta from start X, applies a 1.15 multiplier for a natural drag feel, and updates scrollLeft in real time.
pointerup / pointercancel / pointerleaveEnds the drag, releases pointer capture, removes .is-dragging.

Drag Threshold & Click Guard

A 3px movement threshold distinguishes intentional drags from accidental clicks.

MovementResult
Less than 3pxTreated as a regular click — scroll is not applied.
3px or moreScroll is applied. The next click event on any child is suppressed.

When the threshold is exceeded, a once capture listener is attached to the wrapper that calls preventDefault() and stopImmediatePropagation() on the next click event. This prevents unintended navigation or button activations at the end of a drag.

.is-dragging

While dragging, .is-dragging is added to the .swiper element. Use it to control cursor appearance or disable pointer events on interactive children.

.swiper.is-dragging {
  cursor: grabbing;
}

.swiper.is-dragging a,
.swiper.is-dragging button {
  pointer-events: none;
}

Javascript Runtime

For the swiper to initialize, add the fa-component="swiper" attribute to the swiper element and call new FrontAlign() once on the page. The Smart Observer automatically discovers and initializes supported components. When faApp.dispose() is called, all observers, event listeners, and component instances managed by that FrontAlign runtime are fully cleaned up.

React Usage

For React and Next.js projects, use the useSwiper hook instead of initializing manually. The hook attaches fa-component="swiper" behavior to the ref element and disposes on unmount.

new FrontAlign() and Smart Observer are not used in React — the hook manages the DOM ref directly.

import { useSwiper } from 'frontalign/react';

useSwiper returns a single ref to attach to the .swiper root element.

Return valueTypeDescription
refReact.RefObjectAttach to the .swiper root element via ref=. Initialization runs after mount; disposal runs on unmount via swiperDispose().

Basic usage

import { useSwiper } from 'frontalign/react';

export function ProductCarousel() {
  const ref = useSwiper();

  return (
    <div className="swiper" ref={ref}>
      <div className="swiper-wrapper">
        <div className="swiper-item" style={{ width: 260 }}>Card 1</div>
        <div className="swiper-item" style={{ width: 260 }}>Card 2</div>
        <div className="swiper-item" style={{ width: 260 }}>Card 3</div>
      </div>
    </div>
  );
}

Dynamically rendered items

The hook initializes once on mount. If items are rendered from async data, render the outer structure immediately so the hook has a stable ref to attach to.

import { useSwiper } from 'frontalign/react';

export function FeedCarousel({ posts }: { posts: Post[] }) {
  const ref = useSwiper();

  return (
    <div className="swiper" ref={ref}>
      <div className="swiper-wrapper">
        {posts.map(post => (
          <div key={post.id} className="swiper-item" style={{ width: 280 }}>
            <div className="card">
              <img src={post.thumbnail} alt={post.title} />
              <h3>{post.title}</h3>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

With conditional rendering

When the swiper is conditionally mounted, the hook's cleanup disposes the instance automatically on unmount — no manual swiperDispose() call is needed.

import { useState } from 'react';
import { useSwiper } from 'frontalign/react';

export function GallerySection({ visible }: { visible: boolean }) {
  const ref = useSwiper();

  if (!visible) return null;

  return (
    <div className="swiper" ref={ref}>
      <div className="swiper-wrapper">
    <div className="swiper-item w-2fr3 p-4 bg-blue">
      <div className="card">Card 1</div>
    </div>
    <div className="swiper-item w-2fr3 p-4 bg-indigo">
      <div className="card">Card 2</div>
    </div>
    <div className="swiper-item w-2fr3 p-4 bg-success">
      <div className="card">Card 3</div>
    </div>
  </div>
    </div>
  );
}

Continue with the React Integration guide for provider setup, hooks, and Next.js usage.

Accessibility

Swiper does not manage ARIA attributes automatically — apply them manually for better screen reader support.

Recommended practices:

  • Wrap the swiper in a role="region" with an aria-label describing the carousel content.
  • Add aria-label to each .swiper-item or its primary child so screen readers can identify individual slides.
  • Do not rely on drag as the only navigation method — ensure interactive children (buttons, links) are keyboard accessible.
  • Avoid placing focusable elements inside items that become unreachable when overflowed out of view.
<section role="region" aria-label="Featured products">
  <div class="swiper" fa-component="swiper">
    <div class="swiper-wrapper">
      <div class="swiper-item" style="width: 260px;" aria-label="Product 1">
        <div class="card">Card 1</div>
      </div>
      <div class="swiper-item" style="width: 260px;" aria-label="Product 2">
        <div class="card">Card 2</div>
      </div>
    </div>
  </div>
</section>

Class Reference

ClassRole
.swiperOuter wrapper. Clips overflow and provides responsive max-width.
.swiper-wrapperFlex scroll track. Hides scrollbar, enables touch momentum, sets item gap.
.swiper-itemIndividual slide. Fixed size via flex: 0 0 auto, snaps to start on scroll.
.is-draggingApplied to .swiper during active drag. Use to change cursor or disable child interactions.

FrontAlign