Swiper React Components

Installation

Swiper React is available only via NPM as a part of the main Swiper library:

npm i swiper

Usage

swiper/react exports 2 components: Swiper and SwiperSlide:

// Import Swiper React components
import { Swiper, SwiperSlide } from 'swiper/react';

// Import Swiper styles
import 'swiper/swiper.scss';

export default () => {
  return (
    <Swiper
      spaceBetween={50}
      slidesPerView={3}
      onSlideChange={() => console.log('slide change')}
      onSwiper={(swiper) => console.log(swiper)}
    >
      <SwiperSlide>Slide 1</SwiperSlide>
      <SwiperSlide>Slide 2</SwiperSlide>
      <SwiperSlide>Slide 3</SwiperSlide>
      <SwiperSlide>Slide 4</SwiperSlide>
      ...
    </Swiper>
  );
};

By default Swiper React uses core version of Swiper (without any additional components). If you want to use Navigation, Pagination and other components, you have to install them first.

Here is the list of additional modules imports:

// import Swiper core and required components
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from 'swiper';

import { Swiper, SwiperSlide } from 'swiper/react';

// Import Swiper styles
import 'swiper/swiper.scss';
import 'swiper/components/navigation/navigation.scss';
import 'swiper/components/pagination/pagination.scss';
import 'swiper/components/scrollbar/scrollbar.scss';

// install Swiper components
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);

export default () => {
  return (
    <Swiper
      spaceBetween={50}
      slidesPerView={3}
      navigation
      pagination={{ clickable: true }}
      scrollbar={{ draggable: true }}
      onSwiper={(swiper) => console.log(swiper)}
      onSlideChange={() => console.log('slide change')}
    >
      <SwiperSlide>Slide 1</SwiperSlide>
      <SwiperSlide>Slide 2</SwiperSlide>
      <SwiperSlide>Slide 3</SwiperSlide>
      <SwiperSlide>Slide 4</SwiperSlide>
      ...
    </Swiper>
  );
};

Note, Swiper React component will create required elements for Navigation, Pagination and Scrollbar if you pass these params without specifying its elements (e.g. without navigation.nextEl, pagination.el, etc.)

Styles

Swiper package contains different sets of CSS, Less and SCSS styles:

CSS Styles

CSS styles available only for bundle version:

Less Styles

Less styles are separate styles for core version and components:

SCSS Styles

SCSS styles are also separate styles for core version and components:

Swiper props

Swiper React component receive all Swiper parameters as component props, plus some extra props:

PropTypeDefaultDescription
tagstring'div'Main Swiper container HTML element tag
wrapperTagstring'div'Swiper wrapper HTML element tag
onSwiper(swiper) => voidCallback that receives Swiper instance

Also it supports all Swiper events in on{Eventname} format. For example slideChange event becomes onSlideChange prop:

<Swiper
  onSlideChange={() => {/*...*/}}
  onReachEnd={() => {/*...*/}}
  ...
>

SwiperSlide props

PropTypeDefaultDescription
tagstring'div'Swiper Slide HTML element tag
zoombooleanfalseEnables additional wrapper required for zoom mode
virtualIndexnumberActual swiper slide index. Required to be set for virtual slides

SwiperSlide render function

SwiperSlide component can accept render function that receives an object with the following properties:

For example:

<Swiper>
  <SwiperSlide>
    {({isActive}) => (
      <div>Current slide is {isActive ? 'active' : 'not active'}</div>
    )}
  </SwiperSlide>
</Swiper>

Slots

Swiper React uses "slots" for content distribution. There are 4 slots available

For example:

<Swiper>
  <SwiperSlide>Slide 1</SwiperSlide>
  <SwiperSlide>Slide 2</SwiperSlide>
  <span slot="container-start">Container Start</span>
  <span slot="container-end">Container End</span>
  <span slot="wrapper-start">Wrapper Start</span>
  <span slot="wrapper-end">Wrapper End</span>
</Swiper>

Will be rendered as:

<div class="swiper-container">
  <span slot="container-start">Container Start</span>
  <div class="swiper-wrapper">
    <span slot="wrapper-start">Wrapper Start</span>
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <span slot="wrapper-end">Wrapper End</span>
  </div>
  <span slot="container-end">Container End</span>
</div>

Virtual Slides

Virtual Slides rendering here is fully handled by React and not required anything except setting virtual:true property and setting virtualIndex on slides:

import SwiperCore, { Virtual } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';

// install Virtual module
SwiperCore.use([Virtual]);

export default () => {
  // Create array with 1000 slides
  const slides = Array.from({ length: 1000 }).map((el, index) => `Slide ${index + 1}`);

  return (
    <Swiper spaceBetween={50} slidesPerView={3} virtual>
      {slides.map((slideContent, index) => {
        <SwiperSlide key={slideContent} virtualIndex={index}>{slideContent}</SwiperSlide>;
      })}
    </Swiper>
  );
};

Controller

Controller requires to pass one Swiper instance to another:

import React, { useState } from 'react';
import SwiperCore, { Controller } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';

// install Swiper's Controller component
Swiper.use([Controller]);

const App = () => {
  // store controlled swiper instance
  const [controlledSwiper, setControlledSwiper] = useState(null);

  return (
    <main>
      {/* Main Swiper -> pass controlled swiper instance */}
      <Swiper controller={{ control: controlledSwiper }} ...>
        {/* ... */}
      </Swiper>

      {/* Controlled Swiper -> store swiper instance */}
      <Swiper onSwiper={setControlledSwiper} ...>
        {/* ... */}
      </Swiper>
    </main>
  )
}

For two-way control (when both Swipers control each other) it should be like this:

import React, { useState } from 'react';
import SwiperCore, { Controller } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';

// install Swiper's Controller component
Swiper.use([Controller]);

const App = () => {
  // store swiper instances
  const [firstSwiper, setFirstSwiper] = useState(null);
  const [secondSwiper, setSecondSwiper] = useState(null);

  return (
    <main>
      <Swiper onSwiper={setFirstSwiper} controller={{ control: secondSwiper }}>
        {/* ... */}
      </Swiper>

      <Swiper onSwiper={setSecondSwiper} controller={{ control: firstSwiper }}>
        {/* ... */}
      </Swiper>
    </main>
  )
}

Thumbs

Same as with controller we need to store thumbs instance and pass it to main gallery:

import React, { useState } from 'react';
import SwiperCore, { Thumbs } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';

// install Swiper's Thumbs component
Swiper.use([Thumbs]);

const App = () => {
  // store thumbs swiper instance
  const [thumbsSwiper, setThumbsSwiper] = useState(null);

  return (
    <main>
      {/* Main Swiper -> pass thumbs swiper instance */}
      <Swiper thumbs={{ swiper: thumbsSwiper }} ...>
        {/* ... */}
      </Swiper>

      {/* Thumbs Swiper -> store swiper instance */}
      {/* It is also required to set watchSlidesVisibility and watchSlidesProgress props */ }
      <Swiper
        onSwiper={setThumbsSwiper}
        watchSlidesVisibility
        watchSlidesProgress
        ...
      >
        {/* ... */}
      </Swiper>
    </main>
  )
}

Effects

The following effects are available:

To use effects you have to import and install them first (as all other modules) (Fade example):

import SwiperCore, {EffectFade} from 'swiper';
SwiperCore.use([EffectFade]);

You can find running effect demos here.

Full Fade Effect Example

import React from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import SwiperCore, {EffectFade} from 'swiper';

import 'swiper/swiper.scss';
import 'swiper/components/effect-fade/effect-fade.scss';

SwiperCore.use([EffectFade]);

export default () => {
  return (
    <Swiper effect="fade">
      {[1, 2, 3].map((i, el) => {
        return <SwiperSlide>Slide {el}</SwiperSlide>;
      })}
    </Swiper>
  );
};

Getting Started Video

For a more comprehensive hands-on tutorial have a look at this 15-min getting-started video