This guide is the technical reference for engineers, architects, and maintainers who integrate, extend, audit, or build on Swiper. It documents the library's architecture, its complete public API (every parameter, method, property, and event), the build and packaging system, its styling and CSS-class contract, security posture, and a roadmap of known issues and improvements.
It is the companion to the User Guide (everyday usage and recipes). Where the User Guide shows how to use Swiper, this guide explains how Swiper is built and gives the exhaustive reference tables.
Note
Reference target: Swiper v12.2.0 (package name
swiper), MIT-licensed, authored by Vladimir Kharlampidi. Homepage: swiperjs.com. This document is derived directly from the TypeScript definitions and source.
1. Executive Summary
Swiper is a dependency-free, framework-agnostic touch slider for the web. Its defining engineering characteristics:
- Modular & tree-shakeable. A small core handles layout, touch, and transitions; every feature (navigation, pagination, autoplay, effects, zoom, …) is an independently importable module. Unused modules never enter your bundle.
- Multi-target distribution. One source produces six consumption surfaces: a core ES module, an all-in-one bundle, a React component set, a Vue component set, a Web Component (
<swiper-container>), and per-module CSS. - No runtime dependencies. Swiper ships zero production dependencies. There is no server, no network I/O, no configuration files, and no secrets — it is a client-side UI library configured entirely by a JavaScript options object.
- Type-first API. The authoritative API contract lives in TypeScript declaration files (
.d.ts) whose JSDoc carries the description, type, default, and examples for every option, method, and event.
| Attribute | Value |
|---|---|
| Package | swiper (v12.2.0) |
| License | MIT |
| Module format | ESM ("type": "module") |
| Runtime dependencies | None |
| Install requirement | Node.js >= 4.7.0 (build/install only) |
| Source layout | All source under src/; build emits to dist/ |
| Build tooling | Rollup + Babel (JS), PostCSS/Less + clean-css/cssnano (CSS), custom Node build scripts |
| Targets | Core, Bundle, React, Vue, Element (web component) |
2. Architecture
2.1 High-level structure
┌─────────────────────────────┐
│ Swiper core │
│ (src/core/*) │
│ layout · touch · transition │
│ translate · update · loop │
└───────────────┬──────────────┘
│ lifecycle events + extendParams()
┌────────────────────────────────┼────────────────────────────────┐
│ │ │
┌──────┴───────┐ ┌───────┴────────┐ ┌───────┴────────┐
│ Feature │ │ Effect │ │ Integration │
│ modules │ │ modules │ │ wrappers │
│ (src/modules) │ │ (effect-*) │ │ react/vue/ │
│ navigation │ │ fade/cube/flip │ │ element │
│ pagination │ │ coverflow/cards │ │ │
│ autoplay … │ │ creative │ │ │
└──────────────┘ └────────────────┘ └────────────────┘
dist/ build targets:
swiper.mjs core class
swiper-bundle.mjs core + all modules
modules/index.mjs individual modules (swiper/modules)
swiper-react.mjs React components
swiper-vue.mjs Vue components
swiper-element.mjs <swiper-container> web component
*.css core + per-module styles
2.2 The core (src/core)
The core is responsible for everything that is not an optional feature. Its subfolders map directly to responsibilities (all scored HIGH in source triage):
| Core folder | Responsibility |
|---|---|
src/core |
Constructor, parameter merging, init/destroy lifecycle |
src/core/events |
Touch/pointer event binding (start/move/end), click handling |
src/core/slide |
slideTo / slideNext / slidePrev / slideReset / slideToClosest logic |
src/core/transition |
Transition start/end orchestration |
src/core/translate |
Reading/setting the wrapper translate, min/max translate |
src/core/update |
Size/slides/progress/classes recalculation |
src/core/loop |
Loop slide creation/destruction and "loop fix" |
src/core/breakpoints |
Resolving and applying responsive breakpoints |
src/core/grab-cursor |
Grab-cursor desktop affordance |
src/core/check-overflow |
watchOverflow locking when there aren't enough slides |
src/core/classes |
Computing CSS classes for container and slides |
2.3 The module system
A module is a function conforming to the SwiperModule type (from src/types/shared.d.ts):
export type SwiperModule = (options: {
params: Swiper['params'];
swiper: Swiper;
extendParams: (obj: { [name: string]: any }) => void;
on: Swiper['on'];
once: Swiper['once'];
off: Swiper['off'];
emit: Swiper['emit'];
}) => void;
Each module receives the live instance and the event bus. It:
- Calls
extendParams()to register its own option object and defaults (e.g. thenavigationmodule registers thenavigationoption block). - Subscribes to core lifecycle events (
init,update,slideChange,setTranslate,resize, …) viaon(). - Adds its own state/methods to the instance (e.g.
swiper.navigation,swiper.autoplay) and emits its own events (navigationNext,autoplayStart, …).
Modules are installed either by passing them in the modules array per-instance, or globally with the static Swiper.use([...]). The bundle build pre-installs all of them.
Note
This is why the User Guide repeatedly frames a feature as "three pieces": the module import (JS), the
modulesarray entry (installation), and the CSS import (styling). The architecture enforces that separation to keep the core tiny.
2.4 Integration wrappers
| Wrapper | Source | What it adapts |
|---|---|---|
React (src/react) |
swiper-react.d.ts |
<Swiper> / <SwiperSlide> components; props mirror SwiperOptions; events as on<Event> props; useSwiper()/useSwiperSlide() hooks |
Vue (src/vue) |
swiper-vue.d.ts |
<swiper>/<swiper-slide> components; props mirror options; @event listeners; useSwiper()/useSwiperSlide() composables (reactive refs) |
Element (src/swiper-element.d.ts) |
Web component | <swiper-container>/<swiper-slide> custom elements; Shadow DOM; kebab-case attributes; register() entry |
Shared (src/components-shared, src/shared) |
— | Code shared across the React/Vue/Element wrappers (param parsing, slot handling, event wiring) |
The wrappers are thin: they translate framework idioms (props, slots, reactivity) into the same core SwiperOptions object and instance the User Guide already documented. The React/Vue components additionally manage the instance lifecycle (init on mount, update on prop change, destroy on unmount).
3. Packaging & Distribution
3.1 The exports map (canonical entry points)
The published package's exports field (src/copy/package.json) is the authoritative list of import specifiers. Engineers should treat it as the contract — only these entry points are public.
| Entry point | types |
default |
|---|---|---|
swiper / swiper/core |
swiper.d.ts |
swiper.mjs |
swiper/bundle |
swiper.d.ts |
swiper-bundle.mjs |
swiper/effect-utils |
swiper-effect-utils.d.ts |
swiper-effect-utils.mjs |
swiper/modules |
types/modules/index.d.ts |
modules/index.mjs |
swiper/react |
swiper-react.d.ts |
swiper-react.mjs |
swiper/vue |
swiper-vue.d.ts |
swiper-vue.mjs |
swiper/element |
swiper-element.d.ts |
swiper-element.mjs |
swiper/element/bundle |
swiper-element.d.ts |
swiper-element-bundle.mjs |
swiper/css / swiper/swiper.css |
swiper.css.d.ts |
swiper.css |
swiper/css/bundle |
swiper-bundle.css.d.ts |
swiper-bundle.css |
swiper/css/<module> |
modules/<module>.css.d.ts |
modules/<module>.css |
swiper/element/css/<module> |
modules/<module>-element.css.d.ts |
modules/<module>-element.css |
swiper/types |
types/index.d.ts |
— |
Per-module CSS entry points exist for: a11y, autoplay, controller, effect-coverflow, effect-cube, effect-fade, effect-flip, effect-creative, effect-cards, free-mode, grid, hash-navigation, history, keyboard, manipulation, mousewheel, navigation, pagination, parallax, scrollbar, thumbs, virtual, zoom — and the same set again under swiper/element/css/* for the Shadow-DOM web component.
Important
The web component uses separate
*-element.cssfiles (suffixed-element) because Shadow-DOM-scoped styling differs from light-DOM styling. When using<swiper-container>, inject styles via the element'sinjectStyles/injectStylesUrlsproperties rather than importing global CSS.
3.2 Build pipeline
The build is driven by custom Node scripts (scripts/), orchestrated through npm scripts in the root package.json:
| Command | Purpose |
|---|---|
npm run build |
Development build → dist/ |
npm run build:prod |
Production build → dist/ |
npm run watch |
Rebuild on source change |
npm run core / react / vue / element |
Build + serve the matching playground via Vite |
npm run demos |
Build + serve the demos/ site |
npm run lint |
ESLint (airbnb-base + prettier) |
npm run check-format / format |
Prettier check / write |
npm run validate |
check-format + lint in parallel |
npm test |
validate then build:prod |
npm run release |
validate then the release script |
npm run build-icons-font |
Generate the icon font (Python script) |
npm run changelog |
Conventional-changelog (Angular preset) |
Toolchain (from devDependencies): Rollup (rollup, @rollup/plugin-babel, @rollup/plugin-node-resolve, @rollup/plugin-replace) for JS bundling; Babel (@babel/core, preset-env, preset-react) for transpilation; PostCSS (postcss, postcss-nested, autoprefixer, cssnano) and Less (less) plus clean-css for styles; terser for minification; Vite for the playgrounds.
Note
Per the README's contribution rule, all changes go into
src/only —dist/is generated. Thedist/folder is what consumers should use in production;src/is the editable source of truth.
3.3 Build-time flags
The single build-time configuration value found in source is the environment variable SWIPER_BUILD_MODULES (read via process.env in scripts/utils/helper.js). It controls which modules the build script includes when assembling targets. It is a build concern only — it has no effect at runtime in the browser.
Note
Swiper has no runtime configuration files and no runtime environment variables. All runtime behavior is set through the
SwiperOptionsobject passed to the constructor (documented in §4). There is no.env, no config schema, and no config loader to manage.
4. Complete Parameter Reference (SwiperOptions)
Every core parameter, its type, and its default — taken verbatim from src/types/swiper-options.d.ts. Module-specific option blocks are in §6.
4.1 Initialization & lifecycle
| Parameter | Type | Default | Description |
|---|---|---|---|
modules |
SwiperModule[] |
— | Modules to install on this instance |
init |
boolean |
true |
Auto-initialize on construction; if false, call swiper.init() manually |
enabled |
boolean |
true |
Whether Swiper starts enabled (disabled hides nav and ignores interaction) |
runCallbacksOnInit |
boolean |
true |
Fire transition/slideChange events during init (when initialSlide ≠ 0 or loop) |
initialSlide |
number |
0 |
Index of the slide shown initially |
direction |
'horizontal' | 'vertical' |
'horizontal' |
Slide axis |
speed |
number |
300 |
Transition duration (ms) |
updateOnWindowResize |
boolean |
true |
Recalculate on window resize/orientationchange |
resizeObserver |
boolean |
true |
Use ResizeObserver on the container when available |
userAgent |
string | null |
null |
UA string for SSR device detection |
url |
string | null |
null |
URL for SSR active-slide detection with history |
4.2 Slides grid & sizing
| Parameter | Type | Default | Description |
|---|---|---|---|
slidesPerView |
number | 'auto' |
1 |
Slides visible at once |
slidesPerGroup |
number |
1 |
Slides advanced per action |
slidesPerGroupSkip |
number |
0 |
First N slides treated as single groups |
slidesPerGroupAuto |
boolean |
false |
With slidesPerView:'auto', skip all in-view slides per action |
spaceBetween |
number | string |
0 |
Gap between slides (px) |
centeredSlides |
boolean |
false |
Center the active slide |
centeredSlidesBounds |
boolean |
false |
Center without gaps at the edges (needs centeredSlides) |
slidesOffsetBefore |
number |
0 |
Extra offset before the first slide (px) |
slidesOffsetAfter |
number |
0 |
Extra offset after the last slide (px) |
normalizeSlideIndex |
boolean |
true |
Normalize the active slide index |
centerInsufficientSlides |
boolean |
false |
Center when fewer slides than slidesPerView |
snapToSlideEdge |
boolean |
false |
Always snap to slide edges (fractional/'auto' only) |
setWrapperSize |
boolean |
false |
Set explicit wrapper size (flexbox fallback) |
autoHeight |
boolean |
false |
Container height follows the active slide |
roundLengths |
boolean |
false |
Round slide sizes (avoid blurry text) |
width |
number | null |
null |
Force width (disables responsiveness) |
height |
number | null |
null |
Force height (disables responsiveness) |
maxBackfaceHiddenSlides |
number |
10 |
Threshold for backface-visibility:hidden (Safari flicker fix) |
4.3 Touch, swipe & resistance
| Parameter | Type | Default | Description |
|---|---|---|---|
grabCursor |
boolean |
false |
Show grab cursor on hover |
touchEventsTarget |
'container' | 'wrapper' |
'wrapper' |
Element to listen for touch on |
touchRatio |
number |
1 |
Touch movement ratio |
touchAngle |
number |
45 |
Angle (deg) to trigger a touch move |
simulateTouch |
boolean |
true |
Accept mouse as touch (click-drag) |
shortSwipes |
boolean |
true |
Enable short swipes |
longSwipes |
boolean |
true |
Enable long swipes |
longSwipesRatio |
number |
0.5 |
Threshold ratio for long swipes |
longSwipesMs |
number |
300 |
Min duration (ms) for long swipes |
followFinger |
boolean |
true |
Track finger during drag (vs. animate on release) |
allowTouchMove |
boolean |
true |
Allow drag-to-slide |
threshold |
number |
5 |
Min touch distance (px) before moving |
touchStartPreventDefault |
boolean |
true |
preventDefault on pointerdown |
touchStartForcePreventDefault |
boolean |
false |
Always preventDefault on touchstart |
touchMoveStopPropagation |
boolean |
false |
Stop propagation of touchmove |
edgeSwipeDetection |
boolean | string |
false |
Release events for in-app swipe-back ('prevent' to block system) |
edgeSwipeThreshold |
number |
20 |
Edge area (px) for swipe-back |
touchReleaseOnEdges |
boolean |
false |
Release touch at edges to allow page scroll (needs threshold:0) |
passiveListeners |
boolean |
true |
Use passive listeners where possible |
resistance |
boolean |
true |
Resistant bounds |
resistanceRatio |
number |
0.85 |
Resistance ratio |
preventInteractionOnTransition |
boolean |
false |
Block slide change during transition |
allowSlidePrev |
boolean |
true |
Allow sliding backward |
allowSlideNext |
boolean |
true |
Allow sliding forward |
4.4 Swiping behavior & clicks
| Parameter | Type | Default | Description |
|---|---|---|---|
noSwiping |
boolean |
true |
Disable swiping on noSwipingClass elements |
noSwipingClass |
string |
'swiper-no-swiping' |
Class that disables swiping |
noSwipingSelector |
string |
— | Selector to disable swiping on (e.g. 'input') |
swipeHandler |
CSSSelector | HTMLElement | null |
null |
Restrict swiping to this handle |
preventClicks |
boolean |
true |
Prevent accidental clicks during swipe |
preventClicksPropagation |
boolean |
true |
Stop click propagation during swipe |
slideToClickedSlide |
boolean |
false |
Clicking a slide transitions to it |
focusableElements |
string |
'input, select, option, textarea, button, video, label' |
Elements where swiping is disabled when focused |
uniqueNavElements |
boolean |
true |
Resolve nav/pagination/scrollbar selectors within children first |
4.5 Progress, loop & rewind
| Parameter | Type | Default | Description |
|---|---|---|---|
watchSlidesProgress |
boolean |
false |
Compute each slide's progress/visibility (adds visible class) |
loop |
boolean |
false |
Continuous loop mode |
loopAddBlankSlides |
boolean |
true |
Auto-add blank slides for grid/group evenness in loop |
loopAdditionalSlides |
number |
0 |
Increase number of looped slides |
loopPreventsSliding |
boolean |
true |
Ignore slideNext/Prev while animating in loop |
rewind |
boolean |
false |
Rewind at edges (don't combine with loop) |
4.6 Effects (selector + per-effect blocks)
| Parameter | Type | Default | Description |
|---|---|---|---|
effect |
'slide' | 'fade' | 'cube' | 'coverflow' | 'flip' | 'creative' | 'cards' | string |
'slide' |
Active transition effect |
virtualTranslate |
boolean |
false |
Operate without setting real translate (custom transitions) |
cssMode |
boolean |
false |
Use native CSS Scroll Snap (see note below) |
Warning
cssMode: trueswaps Swiper's JS-driven movement for the browser's CSS Scroll Snap. It can be much faster for simple sliders but does not support: Cube effect; thespeedparameter may have no effect; transition start/end events (useslideChange); limitedslidesPerGroup;simulateTouch/mouse-drag;resistance;allowSlidePrev/Next; andswipeHandler. With 3D effects you must wrap slide content in<div class="swiper-slide-transform">.
The per-effect option objects (fadeEffect, cubeEffect, coverflowEffect, flipEffect, cardsEffect, creativeEffect) are fully documented in §6.
4.7 Responsive & observation
| Parameter | Type | Default | Description |
|---|---|---|---|
breakpoints |
{ [width:number]: SwiperOptions; [ratio:string]: SwiperOptions } |
— | Per-breakpoint parameter overrides (layout params only) |
breakpointsBase |
'window' | 'container' | CSSSelector |
'window' |
Basis for breakpoint keys |
observer |
boolean |
false |
MutationObserver on swiper + elements |
observeParents |
boolean |
false |
Also observe parent elements |
observeSlideChildren |
boolean |
false |
Also observe slide children |
watchOverflow |
boolean |
true |
Lock/disable when there aren't enough slides |
4.8 Element / Web Component parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
createElements |
boolean |
false |
Auto-create wrapper/nav/pagination/scrollbar elements |
eventsPrefix |
string |
'swiper' |
Prefix for DOM events emitted by <swiper-container> |
swiperElementNodeName |
string |
'SWIPER-CONTAINER' |
Node name used to detect web-component rendering |
injectStyles |
string[] |
— | Inline styles injected into the Shadow DOM |
injectStylesUrls |
string[] |
— | Stylesheet <link>s injected into the Shadow DOM |
4.9 CSS class-name parameters (namespacing)
Each of these overrides a default Swiper CSS class. Defaults shown; changing them requires matching CSS changes. (Marked * are not supported in the React/Vue components.)
| Parameter | Default |
|---|---|
containerModifierClass |
'swiper-' |
slideClass * |
'swiper-slide' |
slideActiveClass * |
'swiper-slide-active' |
slideVisibleClass * |
'swiper-slide-visible' |
slideFullyVisibleClass * |
'swiper-slide-fully-visible' |
slideNextClass * |
'swiper-slide-next' |
slidePrevClass * |
'swiper-slide-prev' |
slideBlankClass * |
'swiper-slide-blank' |
wrapperClass * |
'swiper-wrapper' |
lazyPreloaderClass |
'swiper-lazy-preloader' |
lazyPreloadPrevNext |
0 |
4.10 Event registration parameters
| Parameter | Type | Description |
|---|---|---|
on |
{ [event]: handler } |
Register event handlers at init (see §5 for the event list) |
onAny |
(handler) => void |
Catch-all handler invoked for every event |
Note
Negative knowledge The following do not exist as core options and should never be documented as such: there is no
lazycore option (lazy loading is handled vialazyPreloadPrevNext+ theswiper-lazy-preloaderelement and per-slide markup), noautoplaycore boolean independent of the Autoplay module, and no top-levelnavigation/pagination/scrollbarbehavior without importing the matching module. The only build-time variable isSWIPER_BUILD_MODULES; there are no runtime env vars.
5. Complete Events Reference
Core events from src/types/swiper-events.d.ts. Handlers receive the swiper instance as the first argument (plus any listed extras). Register via the on option, swiper.on(name, handler), .once(), or .off().
5.1 Lifecycle events
| Event | Extra args | Fires |
|---|---|---|
beforeInit |
— | Right before init |
init |
— | After init (with swiper.on('init'), only when init:false) |
afterInit |
— | Right after init |
beforeDestroy |
— | Before destroy |
destroy |
— | On destroy |
update |
— | After swiper.update() |
5.2 Slide-change events
| Event | Fires |
|---|---|
slideChange |
Active slide changed |
beforeSlideChangeStart |
Before slide-change starts |
slideChangeTransitionStart / slideChangeTransitionEnd |
Slide-change animation start / end |
slideNextTransitionStart / slideNextTransitionEnd |
Forward-direction only |
slidePrevTransitionStart / slidePrevTransitionEnd |
Backward-direction only |
slideResetTransitionStart / slideResetTransitionEnd |
Reset-to-current animation start / end |
activeIndexChange |
activeIndex changed |
snapIndexChange |
snapIndex changed |
realIndexChange |
realIndex changed (loop) |
5.3 Transition & translate events
| Event | Extra args | Fires |
|---|---|---|
beforeTransitionStart |
speed, internal |
Before a transition starts |
transitionStart / transitionEnd |
— | Transition start / end |
setTranslate |
translate |
Wrapper position changed |
setTransition |
transition |
Animation duration set |
momentumBounce |
— | Momentum bounce occurred |
5.4 Pointer / interaction events
Each receives (swiper, event) where event is a MouseEvent \| TouchEvent \| PointerEvent (except sliderFirstMove, which receives a TouchEvent):
touchStart, touchMove, touchMoveOpposite, sliderMove, sliderFirstMove, touchEnd, click, tap, doubleTap, doubleClick.
5.5 Position / edge events
| Event | Extra args | Fires |
|---|---|---|
progress |
progress (0–1) |
Progress changed |
reachBeginning |
— | Reached the first slide |
reachEnd |
— | Reached the last slide |
toEdge |
— | Moved to an edge |
fromEdge |
— | Moved away from an edge |
lock / unlock |
— | Locked / unlocked (via watchOverflow) |
5.6 Layout / structural events
| Event | Extra args | Fires |
|---|---|---|
slidesUpdated |
— | Slides + sizes recalculated |
slidesLengthChange |
— | Number of slides changed |
slidesGridLengthChange |
— | Slides grid changed |
snapGridLengthChange |
— | Snap grid changed |
resize / beforeResize |
— | On resize handling |
orientationchange |
— | Device orientation changed |
observerUpdate |
— | Observer detected DOM mutation |
breakpoint |
breakpointParams |
Breakpoint changed |
beforeLoopFix / loopFix |
— | Around loop rearrangement |
changeDirection |
— | Direction changed |
Note
Events prefixed with
_(e.g._beforeBreakpoint,_containerClasses,_slideClass,_swiper,_freeModeNoMomentumRelease) are internal. They are emitted for internal/integration plumbing and are not part of the stable public API — do not rely on them.
Module events (e.g. autoplayStart, navigationNext, paginationRender, zoomChange, hashChange, scrollbarDragMove, keyPress, scroll) are listed with their modules in §6.
6. Module Reference
For each module: its option object (with defaults), the instance methods it adds, and the events it emits. Source: src/types/modules/*.d.ts.
6.1 Navigation
Options: enabled?, nextEl/prevEl (null), addIcons (true), hideOnClick (false), disabledClass ('swiper-button-disabled'), hiddenClass ('swiper-button-hidden'), lockClass ('swiper-button-lock'), navigationDisabledClass ('swiper-navigation-disabled').
Instance (swiper.navigation): nextEl, prevEl, update(), init(), destroy().
Events: navigationShow, navigationHide, navigationPrev, navigationNext.
6.2 Pagination
Options: enabled?, el (null), type ('bullets'), bulletElement ('span'), dynamicBullets (false), dynamicMainBullets (1), hideOnClick (true), clickable (false), progressbarOpposite (false), render hooks renderBullet/renderFraction/renderProgressbar/renderCustom, formatFractionCurrent/formatFractionTotal, plus class names: bulletClass ('swiper-pagination-bullet'), bulletActiveClass ('swiper-pagination-bullet-active'), modifierClass ('swiper-pagination-'), currentClass, totalClass, hiddenClass, progressbarFillClass, progressbarOppositeClass, clickableClass, lockClass, horizontalClass, verticalClass, paginationDisabledClass.
Instance (swiper.pagination): el, bullets[], render(), update(), init(), destroy().
Events: paginationRender, paginationUpdate, paginationShow, paginationHide.
6.3 Scrollbar
Options: enabled?, el (null), hide (true), draggable (false), snapOnRelease (false), dragSize ('auto'), lockClass ('swiper-scrollbar-lock'), dragClass ('swiper-scrollbar-drag'), scrollbarDisabledClass, horizontalClass, verticalClass.
Instance (swiper.scrollbar): el, dragEl, updateSize(), setTranslate(), init(), destroy().
Events: scrollbarDragStart, scrollbarDragMove, scrollbarDragEnd (each receives the pointer event).
6.4 Autoplay
Options: delay (3000), stopOnLastSlide (false), disableOnInteraction (true), reverseDirection (false), waitForTransition (true), pauseOnMouseEnter (false).
Instance (swiper.autoplay): running, paused, timeLeft, start(), stop(), pause(), resume().
Events: autoplayStart, autoplayStop, autoplayPause, autoplayResume, autoplay, autoplayTimeLeft(swiper, timeLeft, percentage).
Per-slide override: data-swiper-autoplay="<ms>".
6.5 Keyboard
Options: enabled (false), onlyInViewport (true), pageUpDown (true), speed.
Instance (swiper.keyboard): enabled, enable(), disable().
Events: keyPress(swiper, keyCode).
6.6 Mousewheel
Options: enabled (false), forceToAxis (false), releaseOnEdges (false), invert (false), sensitivity (1), eventsTarget ('container'), thresholdDelta (null), thresholdTime (null), noMousewheelClass ('swiper-no-mousewheel').
Instance (swiper.mousewheel): enabled, enable(), disable().
Events: scroll(swiper, WheelEvent).
6.7 Zoom
Options: limitToOriginalSize (false), maxRatio (3), minRatio (1), panOnMouseMove (false), toggle (true), containerClass ('swiper-zoom-container'), zoomedSlideClass ('swiper-slide-zoomed').
Instance (swiper.zoom): enabled, scale, enable(), disable(), in(ratio?), out(), toggle(event?).
Events: zoomChange(swiper, scale, imageEl, slideEl).
6.8 Thumbs
Options: swiper (null — a Swiper instance, selector, or params), slideThumbActiveClass ('swiper-slide-thumb-active'), thumbsContainerClass ('swiper-thumbs'), multipleActiveThumbs (true), autoScrollOffset (0).
Instance (swiper.thumbs): swiper, update(initial, p?), init().
6.9 Virtual
Options: enabled (false), slides ([]), slidesPerViewAutoSlideSize (320), cache (true), addSlidesBefore (0), addSlidesAfter (0), renderSlide (null), renderExternal (null), renderExternalUpdate (true).
Instance (swiper.virtual): cache, from, to, slides[], appendSlide(), prependSlide(), removeSlide(), removeAllSlides(), update(force).
6.10 Free Mode
Options: enabled (false), momentum (true), momentumRatio (1), momentumVelocityRatio (1), momentumBounce (true), momentumBounceRatio (1), minimumVelocity (0.02), sticky (false).
Instance (swiper.freeMode): onTouchMove(), onTouchEnd().
6.11 Grid
Options: rows (1), fill ('column' — 'row' or 'column').
6.12 Controller
Options: control (Swiper instance(s), selector, or element — null), inverse (false), by ('slide' — 'slide' or 'container').
Instance (swiper.controller): control.
6.13 A11y
Options (enabled by default): enabled (true), prevSlideMessage ('Previous slide'), nextSlideMessage ('Next slide'), firstSlideMessage ('This is the first slide'), lastSlideMessage ('This is the last slide'), paginationBulletMessage ('Go to slide {{index}}'), notificationClass ('swiper-notification'), containerMessage (null), containerRoleDescriptionMessage (null), containerRole (null), itemRoleDescriptionMessage (null), slideLabelMessage ('{{index}} / {{slidesLength}}'), slideRole ('group'), id (null), scrollOnFocus (true), wrapperLiveRegion (true).
Placeholders: {{index}}, {{slidesLength}}.
6.14 Hash Navigation
Options: watchState (false), replaceState (false), getSlideIndex(swiper, hash) (for virtual slides).
Events: hashChange, hashSet.
6.15 History
Options: enabled (false), root (''), replaceState (false), key ('slides'), keepQuery (false).
Per-slide URL segment via data-history="<value>".
6.16 Parallax
Options: enabled (false). Parallaxed elements inside slides use data-swiper-parallax* attributes.
6.17 Manipulation (core only)
Adds slide-editing methods to the instance: appendSlide(), prependSlide(), addSlide(index, slides), removeSlide(indexOrIndexes), removeAllSlides(). Accepts HTML strings or HTMLElement(s). In React/Vue, manipulate the data source instead.
6.18 Effect modules
| Module | Options (defaults) |
|---|---|
EffectFade |
crossFade (false) |
EffectCube |
slideShadows (true), shadow (true), shadowOffset (20), shadowScale (0.94) |
EffectCoverflow |
slideShadows (true), rotate (50), stretch (0, number or %), depth (100), scale (1), modifier (1) |
EffectFlip |
slideShadows (true), limitRotation (true) |
EffectCards |
slideShadows (true), rotate (true), perSlideRotate (2), perSlideOffset (8) |
EffectCreative |
prev/next transform objects, limitProgress (1), shadowPerProgress (false), progressMultiplier (1), perspective (true) |
The EffectCreative prev/next transform shape: { translate?: (string|number)[]; rotate?: number[]; opacity?: number; scale?: number; shadow?: boolean; origin?: string }.
7. Instance API (Swiper class)
From src/types/swiper-class.d.ts.
7.1 Construction & statics
new Swiper(container: CSSSelector | HTMLElement, options?: SwiperOptions)
| Static | Purpose |
|---|---|
Swiper.use(modules) |
Install modules globally |
Swiper.defaults |
The default options object |
Swiper.extendDefaults(options) |
Extend global defaults |
Swiper.extendedDefaults |
Current global extended defaults |
7.2 Navigation methods
| Method | Returns | Purpose |
|---|---|---|
slideNext(speed?, runCallbacks?) |
boolean |
Go to next slide |
slidePrev(speed?, runCallbacks?) |
boolean |
Go to previous slide |
slideTo(index, speed?, runCallbacks?) |
boolean |
Go to a specific index |
slideToLoop(index, speed?, runCallbacks?) |
Swiper |
Go to a slide by real index (loop) |
slideReset(speed?, runCallbacks?) |
boolean |
Reset to the active slide |
slideToClosest(speed?, runCallbacks?) |
boolean |
Snap to the closest slide |
setProgress(progress, speed?) |
void |
Set translate progress (0–1) |
7.3 Update / layout methods
update(), updateSize(), updateSlides(), updateProgress(), updateSlidesClasses(), updateAutoHeight(speed?), slidesPerViewDynamic(), changeDirection(direction?, needUpdate?), changeLanguageDirection('rtl' | 'ltr').
7.4 Translate methods
setTranslate(value), getTranslate(), translateTo(translate, speed, runCallbacks?, translateBounds?), minTranslate(), maxTranslate(), setGrabCursor(), unsetGrabCursor().
7.5 Lifecycle & events methods
init(el?), destroy(deleteInstance?, cleanStyles?), enable(), disable(), attachEvents(), detachEvents(), on(event, handler), once(event, handler), off(event, handler?), emit(event, ...args), onAny(handler), offAny(handler).
7.6 Key instance properties (read state)
| Property | Type | Meaning |
|---|---|---|
params / originalParams |
SwiperOptions |
Effective / original options |
el / wrapperEl / slidesEl |
HTMLElement |
Container / wrapper / slides container |
slides |
HTMLElement[] |
Slide elements |
width / height |
number |
Container size |
translate |
number |
Current wrapper translate |
progress |
number |
0–1 progress |
activeIndex |
number |
Active slide index (DOM order) |
realIndex |
number |
Active slide real index (loop) |
previousIndex / snapIndex |
number |
Previous active / current snap index |
snapGrid / slidesGrid / slidesSizesGrid |
number[] |
Computed grids |
isBeginning / isEnd |
boolean |
At first / last position |
isLocked |
boolean |
Locked by watchOverflow |
animating |
boolean |
In transition |
swipeDirection |
'prev' | 'next' |
Current swipe direction |
touches |
{ startX, startY, currentX, currentY, diff } |
Touch state |
clickedIndex / clickedSlide |
number / HTMLElement |
Last clicked slide |
allowSlideNext / allowSlidePrev / allowTouchMove |
boolean |
Writable gates |
enabled |
boolean |
Instance enabled |
| Module namespaces | object | swiper.navigation, swiper.pagination, swiper.autoplay, swiper.zoom, swiper.thumbs, swiper.virtual, etc. (present when the module is installed) |
Note
Properties documented
!INTERNALin the source (loopedSlides,rtlTranslate,currentBreakpoint,destroyed,modules,loopCreate(),loopDestroy(),isHorizontal(),getBreakpoint(),setBreakpoint()) are implementation details and not part of the supported public API.
8. Styling & CSS Contract
8.1 Required structure & default classes
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide">...</div>
<div class="swiper-slide">...</div>
</div>
<!-- optional module elements -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<div class="swiper-pagination"></div>
<div class="swiper-scrollbar"></div>
</div>
Swiper computes state classes on slides at runtime: swiper-slide-active, swiper-slide-next, swiper-slide-prev, swiper-slide-visible, swiper-slide-fully-visible, swiper-slide-blank, swiper-slide-zoomed, and container modifier classes prefixed swiper- (direction, effect, RTL, locked, etc.). Module elements get their own state classes (e.g. swiper-button-disabled, swiper-pagination-bullet-active).
8.2 Light DOM vs Shadow DOM
Two parallel CSS sets exist:
- Light DOM (
swiper/css,swiper/css/<module>) — for the core/React/Vue usage where slides are in the normal document. - Shadow DOM (
swiper/element/css/<module>, files suffixed-element) — for the<swiper-container>web component, whose internals are encapsulated. Inject these viainjectStyles/injectStylesUrls.
Important
A recurring community request (issue #8164) asks Swiper to ship its built-in classes at 0 CSS specificity so apps can override them more easily. When theming, prefer overriding via the documented class-name parameters (§4.9) or layering your own classes rather than fighting specificity.
9. Security
Swiper is a client-side UI library: it has no server component, no network calls, no filesystem access, no credentials, and no environment-variable configuration. The attack surface is therefore limited to what runs in the user's browser when slides and options are rendered. Key considerations:
9.1 Known vulnerability class — prototype pollution
The project's issue tracker shows active security work in the prototype pollution class:
- #8189 — "Incomplete Fix for CVE-2026-27212" (open): indicates a follow-up to a previously addressed CVE; the fix was reported as incomplete and is under review.
- #8167 — "Can you backport the prototype pollution fix to v11?" (closed): a prototype-pollution fix landed and a backport to the v11 line was requested.
Implication for integrators:
Caution
Prototype-pollution issues in a slider typically arise when untrusted data is merged into the options object (deep-merge of attacker-controlled keys like
__proto__). If you build Swiper options from user-supplied or third-party JSON, sanitize keys before passing them tonew Swiper(...), and stay on the latest patched v12.x release. Track issue #8189 for the current state of CVE-2026-27212.
9.2 DOM injection through render hooks
Several options accept HTML strings or render functions that produce HTML: pagination.renderBullet/renderFraction/renderProgressbar/renderCustom, virtual.renderSlide/renderExternal, and the Manipulation methods (appendSlide, prependSlide, addSlide) accept raw HTML strings.
Warning
Treat all of these as
innerHTMLsinks. Never pass unescaped user content into render hooks orappendSlide/addSlide. Escape or sanitize first, or buildHTMLElements yourself rather than passing HTML strings.
9.3 Web component & Shadow DOM
The <swiper-container> element injects styles into a Shadow Root. One closed community issue (#8169) reported a NotAllowedError setting adoptedStyleSheets on a ShadowRoot in certain environments — a robustness rather than confidentiality concern, but worth noting for constrained runtimes (e.g. some embedded/CSP-restricted contexts).
9.4 Hardening checklist
- [ ] Pin to the latest patched
swiper@12release; watch the tracker for CVE follow-ups. - [ ] Sanitize any externally sourced data before it reaches the options object (guard against
__proto__/constructorkeys). - [ ] Sanitize/escape content used in
renderBullet/renderSlide/appendSlide/addSlide. - [ ] Apply a Content Security Policy; Swiper does not require
evalor remote script. - [ ] If embedding via the web component, verify
adoptedStyleSheetssupport in your target runtimes.
10. Performance Tuning
| Lever | Effect |
|---|---|
| Core + per-module imports | Smallest bundle; the bundle build ships every module |
Virtual module |
Keeps only near-viewport slides in the DOM for large data sets |
lazyPreloadPrevNext |
Limit preloaded neighbor slides |
cssMode: true |
Offload movement to native CSS Scroll Snap (with the feature caveats in §4.6) |
resizeObserver (default on) |
Cheaper container-resize detection than window resize |
observer/observeParents |
Use only when contents actually change; mutation observation has a cost |
roundLengths |
Avoids sub-pixel blur; minor cost |
maxBackfaceHiddenSlides |
Tune the Safari flicker workaround; keep low on huge slide counts |
watchSlidesProgress |
Enables per-slide visibility classes — only enable if you use them |
Tip
For content- or image-heavy carousels with many slides, the highest-impact change is the
Virtualmodule. For simple sliders that don't need Swiper's richer features,cssModecan substantially reduce JS work.
11. Development & Contributing
- Edit source only. Per the README, all changes go into
src/;dist/is generated and must not be hand-edited. - Source of truth for the API is the TypeScript declarations under
src/types/— option/method/event descriptions and defaults live in their JSDoc. - Validate before committing:
npm run validate(Prettier check + ESLint). The fullnpm testruns validate then a production build. - Playgrounds:
npm run core | react | vue | elementbuild and serve the matching example app underplayground/via Vite;npm run demosserves the broaderdemos/site. Use these to manually verify behavior across all four targets. - Releases:
npm run releaseruns validation then the release script;npm run changelogregeneratesCHANGELOG.mdusing the Angular conventional-changelog preset. - Conventions: ESLint (airbnb-base) + Prettier are enforced; the codebase is ESM-only.
12. Known Issues & Improvement Areas
Drawn from the project's issue tracker (community-reported). These reflect real, open friction points an integrator may encounter and a maintainer may prioritize.
12.1 Loop mode
Loop mode is the most frequent source of open issues:
- #8076 — loop mode not working correctly in some configurations.
- #7586 — Swiper warns about a "wrong number of slides for loop mode" even when the count seems valid.
- #8178 —
loopAdditionalSlidesdoesn't behave as expected in certain conditions. - #7478 / #8095 —
slideToClickedSlide+centeredSlides+loopinteractions break the loop or block link clicks. - #7254 — request to set a fixed number of duplicated slides to stabilize loop behavior.
Note
The recurring theme: loop's slide-rearrangement interacts badly with
centeredSlides,slideToClickedSlide, and fractionalslidesPerView. When auditing a looped slider, test these combinations explicitly and preferrealIndex/slideToLoopin app code.
12.2 Accessibility
- #8181 — improve accessibility in loop mode.
- #7975 — redundant
aria-disabledadded alongside the nativedisabledattribute on navigation buttons. - #5844 — option to disable the
span.swiper-notificationlive region.
12.3 Web component (Element) parity
- #8125 —
<swiper-container>doesn't render the last two slides withloop+slidesPerView="auto"+ custom slide width. - #7151 — pagination dots malfunction in loop mode in the Svelte/Element integration.
- #8173 — request to expose
isEnd/isBeginningstate on the host element for CSS styling.
12.4 Effects & rendering
- #8168 — Cube (and possibly other) effects show graphics glitches on Electron/WebKit.
- #8161 — pagination button icons slightly clipped.
12.5 Feature requests of note
- #8086 / #6882 — desktop zoom and single-click zoom enhancements.
- #8174 — expose
isFullyVisiblein the ReactSwiperSliderender props. - #8164 — ship built-in classes at 0 specificity for easier overriding.
12.6 Maintainer-facing observations
- Loop semantics need clearer guardrails. Several issues stem from users not satisfying loop's slide-count requirements; surfacing the requirement earlier (or auto-correcting more aggressively than
loopAddBlankSlides) would reduce churn. - Element/web-component parity lags the React/Vue wrappers in a few cases (last-slides rendering, pagination in loop, exposing state to the host). Integrators targeting the web component should test the specific feature combinations above.
- Security follow-through. With an open "incomplete fix" on a CVE (#8189), integrators should pin to the latest patch and maintainers should prioritize closing the prototype-pollution thread and backports.
13. Quick Reference
| Need | Do |
|---|---|
| Install | npm install swiper |
| Core import | import Swiper from 'swiper' + import 'swiper/css' |
| Add a module | import { X } from 'swiper/modules' → modules:[X] → import 'swiper/css/x' |
| Everything at once | import Swiper from 'swiper/bundle' + import 'swiper/css/bundle' |
| React | import { Swiper, SwiperSlide } from 'swiper/react' |
| Vue | import { Swiper, SwiperSlide } from 'swiper/vue' |
| Web component | import { register } from 'swiper/element/bundle'; register() |
| Build (prod) | npm run build:prod → dist/ |
| Validate | npm run validate |
| Active index | swiper.activeIndex (swiper.realIndex in loop) |
| Navigate in code | slideNext() / slidePrev() / slideTo(i) / slideToLoop(i) |
| Recalculate | swiper.update() or observer:true |
| Tear down | swiper.destroy() |