Skip to content

Documentation

Get alpine-js-swiper installed, then drive Swiper with Alpine expressions, $swiper, and event directives.

On this page

Install in two steps.

Requires Alpine.js 3. Swiper is bundled with the plugin, so you do not install it separately.

1. Add the package

Install with npm
npm install alpine-js-swiper

2. Register the plugin

Import the plugin and its stylesheet before calling Alpine.start().

main.js
import Alpine from 'alpinejs';
import AlpineSwiper from 'alpine-js-swiper';
import 'alpine-js-swiper/style.css';

Alpine.plugin(AlpineSwiper);
Alpine.start();

Or drop it in with a CDN.

Load the stylesheet and alpine-js-swiper before Alpine.js. Both scripts may use defer. Pin the same release tag in production.

index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/BillyNoyes/alpine-js-swiper@v1.1.1/dist/style.css">
<script defer src="https://cdn.jsdelivr.net/gh/BillyNoyes/alpine-js-swiper@v1.1.1/dist/alpine-js-swiper.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>

<div x-data x-swiper="{ loop: true }" class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">First</div>
    <div class="swiper-slide">Second</div>
    <div class="swiper-slide">Third</div>
  </div>
  <button type="button" @click="$swiper.slidePrev()">Previous</button>
  <button type="button" @click="$swiper.slideNext()">Next</button>
</div>

Configure with Alpine expressions.

Pass any Swiper parameters to x-swiper. Options are evaluated when the directive initializes. For manual init, pass init: false and call $swiper.init() when ready.

x-swiper options
<div
  x-data="{
    options: {
      slidesPerView: 1,
      spaceBetween: 24,
      breakpoints: {
        768: { slidesPerView: 2 },
        1024: { slidesPerView: 3 }
      }
    }
  }"
  x-swiper="options"
  class="swiper"
>
  <div class="swiper-wrapper">
    <div class="swiper-slide">One</div>
    <div class="swiper-slide">Two</div>
    <div class="swiper-slide">Three</div>
  </div>
</div>

Call methods. Read reactive state.

$swiper is available on the slider element and its descendants. Use realIndex for the visible slide when loop mode is on.

$swiper
<div x-data x-swiper class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">One</div>
    <div class="swiper-slide">Two</div>
    <div class="swiper-slide">Three</div>
  </div>

  <button type="button" @click="$swiper.slidePrev()" :disabled="$swiper.isBeginning">
    Previous
  </button>
  <button type="button" @click="$swiper.slideNext()" :disabled="$swiper.isEnd">
    Next
  </button>
  <span>
    Slide <span x-text="$swiper.realIndex + 1"></span>
    of <span x-text="$swiper.slides"></span>
  </span>
</div>
  • activeIndex: Swiper's internal index
  • realIndex: content index without loop duplicates
  • isBeginning / isEnd: edge state
  • slides / progress: count and 0-1 progress

Bind Swiper events.

Prefix a kebab-case Swiper event with x-swiper-event:. Listeners are removed automatically when Alpine cleans up the element.

x-swiper-event
<div
  x-data="{ message: 'Waiting…' }"
  x-swiper
  x-swiper-event:init="message = 'Ready'"
  x-swiper-event:slide-change="message = `Showing slide ${$swiper.realIndex + 1}`"
  class="swiper"
>
  <div class="swiper-wrapper">
    <div class="swiper-slide">One</div>
    <div class="swiper-slide">Two</div>
  </div>
  <p x-text="message"></p>
</div>

Control sliders from outside.

Give a slider data-swiper-id when controls live outside its DOM subtree, then use $store.swipers.

$store.swipers
<div x-data>
  <div data-swiper-id="gallery" x-swiper class="swiper">
    <div class="swiper-wrapper">
      <div class="swiper-slide">Front</div>
      <div class="swiper-slide">Back</div>
    </div>
  </div>

  <button type="button" @click="$store.swipers.getSwiper('gallery')?.slideTo(0)">
    Show front image
  </button>
</div>

Troubleshooting

Slides are stacked or unstyled

Import alpine-js-swiper/style.css or load dist/style.css from the CDN. The JavaScript bundle cannot apply Swiper’s stylesheet for you.

$swiper is undefined

Use it on the x-swiper element or a descendant. For sibling controls, set data-swiper-id and use $store.swipers.

CDN build does not initialize

Keep script order as alpine-js-swiper first, Alpine.js second. Use matching branch, commit, or release tags for CSS and JS.

progress looks stuck in loop mode

$swiper.progress mirrors Swiper’s translate progress. With loop and a fractional slidesPerView, that value may plateau below 1 while realIndex keeps cycling. Prefer realIndex for slide position UI.