Swiper

A carousel built on Swiper 14: a track of slides with keyboard support, arrows and pagination, configured entirely from Blade props.

<x-atlas::swiper>

<x-atlas::swiper label="Recent projects" title="<h2 class='atlas-heading atlas-heading--h3'>Recent projects</h2>">
    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-slide-1/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-slide-2/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-slide-3/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-slide-4/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

Three tags make up a carousel. <x-atlas::swiper> is the region and the track, <x-atlas::swiper.item> is one slide, and <x-atlas::swiper.navigation> is the arrows-and-pagination group — which the parent renders for you, so you rarely write it yourself. Every direct child of the track must be a swiper.item: Swiper measures those children, and a stray wrapper becomes one enormous slide.

title is a prop rather than a slot, and it is printed unescaped, so pass finished markup. It shares its row with the navigation when the navigation sits at the top.

Slides per view

slidesPerView in :options applies from 1024px up. Below that Swiper is hard-coded to 1.2 slides, so this is a desktop decision only and no breakpoint of yours will change the mobile figure. Keep a fraction in the value — the sliver of the next slide is what tells a visitor there is more to the right.

<x-atlas::swiper label="Case studies" :options="['slidesPerView' => 3]">
    <x-atlas::swiper.item>
        <x-atlas::card image="https://picsum.photos/seed/atlas-spv-1/480/480" title="Quay wall" subtitle="Rotterdam" url="/components/card" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::card image="https://picsum.photos/seed/atlas-spv-2/480/480" title="Lock gates" subtitle="IJmuiden" url="/components/card" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::card image="https://picsum.photos/seed/atlas-spv-3/480/480" title="Tidal park" subtitle="Dordrecht" url="/components/card" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::card image="https://picsum.photos/seed/atlas-spv-4/480/480" title="Storm barrier" subtitle="Zeeland" url="/components/card" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

Pagination

Bullets are the default and the only clickable type: they are destinations, so use them when a visitor might want to jump. A fraction counter suits a long run where a row of dots would be unreadable, and it is the one type that tells you how much is left.

<x-atlas::swiper label="Site photographs" pagination-type="fraction">
    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-frac-1/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-frac-2/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-frac-3/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-frac-4/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-frac-5/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

A progress bar reads as movement through a sequence rather than a set of places, which fits a story told in order. Neither it nor the fraction responds to clicks — leave the arrows on.

<x-atlas::swiper label="Build stages" pagination-type="progressbar">
    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-prog-1/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-prog-2/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-prog-3/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-prog-4/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

pagination-style="wide" redraws bullets as one joined bar. It only affects the bullets type, and reads best with a handful of slides. Set pagination-disabled to keep the arrows and drop the indicator entirely, or :has-navigation="false" to remove the whole group — which leaves swiping and the keyboard as the only way through.

<x-atlas::swiper label="Materials" pagination-style="wide">
    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-wide-1/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-wide-2/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item>
        <x-atlas::image src="https://picsum.photos/seed/atlas-wide-3/640/480" aspect="4/3" alt="" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

The navigation sits in the title row by default, pushed to the far end of it. Move it underneath with navigation-placement="bottom" when the title needs the space or the controls should read as belonging to the track. navigation-position only does anything down there: at the top the title row's own layout decides where the group lands.

Slide labels

Slides are announced as "slide" unless you pass both index and total, which turns that into "Slide 2 of 3". Either one alone is ignored, and so is an index of 0 — count from 1.

<x-atlas::swiper label="Team" pagination-disabled>
    <x-atlas::swiper.item :index="1" :total="3">
        <x-atlas::card.employee image="https://picsum.photos/seed/atlas-team-1/360/480" title="Lotte Verhoeven" subtitle="Lead engineer" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item :index="2" :total="3">
        <x-atlas::card.employee image="https://picsum.photos/seed/atlas-team-2/360/480" title="Sander de Wit" subtitle="Project manager" />
    </x-atlas::swiper.item>

    <x-atlas::swiper.item :index="3" :total="3">
        <x-atlas::card.employee image="https://picsum.photos/seed/atlas-team-3/360/480" title="Noor Bakker" subtitle="Head of research" />
    </x-atlas::swiper.item>
</x-atlas::swiper>
Preview follows the site's light/dark mode. Open standalone →

Reference

<x-atlas::swiper>

  • Name
    title
    Type
    string
    Default
    default: null
    Description
    Markup rendered above the track, next to the navigation. Rendered unescaped, so a heading component can go in it.
  • Name
    label
    Type
    string
    Default
    default: Carousel
    Description
    aria-label for the carousel region. Set it whenever a page holds more than one.
  • Name
    id
    Type
    string
    Default
    default: null
    Description
    DOM id for the section. Generated when omitted, and the track id is derived from it.
  • Name
    options
    Type
    array
    Default
    default: []
    Description
    Swiper options passed to the JS instance. Any key from Swiper's SwiperOptions is valid (e.g. slidesPerView, loop, spaceBetween, autoplay).
  • Name
    has-navigation
    Type
    bool
    Default
    default: true
    Description
    Whether to render the arrows-and-pagination group at all.
  • Name
    navigation-placement
    Type
    top | bottom
    Default
    default: top
    Description
    Whether the navigation sits in the title row or under the track.
  • Name
    navigation-position
    Type
    left | right | center
    Default
    default: right
    Description
    Alignment of the navigation group. Only takes effect with navigation-placement="bottom".
  • Name
    pagination-type
    Type
    bullets | fraction | progressbar
    Default
    default: bullets
    Description
    Pagination style passed to Swiper. Bullets are clickable; the other two are not.
  • Name
    pagination-style
    Type
    normal | wide
    Default
    default: normal
    Description
    Bullet shape. wide turns them into a joined bar, and only affects the bullets type.
  • Name
    pagination-disabled
    Type
    bool
    Default
    default: false
    Description
    Drops the pagination and keeps the arrows.
  • Name
    overflow-hidden
    Type
    bool
    Default
    default: true
    Description
    Set false to let slides bleed past the container edge instead of being clipped.

Slots

  • Name
    default
    Type
    slot
    Description
    The slides. Every child must be a swiper.item, since Swiper measures the track's direct children.

<x-atlas::swiper.item>

  • Name
    index
    Type
    int
    Default
    default: null
    Description
    Position of this slide, from 1. Combined with total it produces a "Slide 2 of 5" label.
  • Name
    total
    Type
    int
    Default
    default: null
    Description
    Number of slides. Needed alongside index; either one on its own is ignored.

Slots

  • Name
    default
    Type
    slot
    Description
    Slide contents.

<x-atlas::swiper.navigation>

  • Name
    controls
    Type
    string
    Default
    default: null
    Description
    id of the track the arrows control, used for aria-controls.
  • Name
    alignment
    Type
    left | right | center
    Default
    default: right
    Description
    Alignment of the group within its row.
  • Name
    pagination-type
    Type
    bullets | fraction | progressbar
    Default
    default: bullets
    Description
    Which pagination modifier class the group carries.
  • Name
    pagination-style
    Type
    normal | wide
    Default
    default: normal
    Description
    Bullet shape modifier.
  • Name
    pagination-disabled
    Type
    bool
    Default
    default: false
    Description
    Renders the arrows without the pagination element between them.
  • Name
    style
    Type
    string
    Default
    default: dots
    Description
    Declared but never read by the view. Leave it alone.