Skip to main content

Swiper Carousel

A reusable horizontally scrollable card carousel with numbered pagination bullets. Uses Swiper.js v8. No build tooling required — all code goes in Webflow page-level custom code.


Assets (page <head>)

Add to Page Settings → Custom Code → Inside <head> tag:

<script src="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css">

Use a single version of Swiper per page. Mixing v4 (legacy) and v8 causes conflicts.


HTML structure (Webflow Designer)

Build the following structure in Designer using Div Blocks. Set IDs and classes as shown:

<div id="products-swiper" class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide">Card 1 content</div>
<div class="swiper-slide">Card 2 content</div>
<div class="swiper-slide">Card 3 content</div>
</div>
<div class="products_pagination swiper-pagination"></div>
</div>
<button class="products-left-button">Prev</button>
<button class="products-right-button">Next</button>

The navigation buttons can be any element type — Links, Divs, or Icons work equally well.


Pagination bullet styling

Add to Page Settings → Custom Code → Inside <head> tag (after the Swiper CSS):

<style>
.swiper-pagination-bullet {
width: 2.25rem !important; height: 2.25rem !important;
text-align: center !important; line-height: 24px !important;
font-size: 16px !important; font-weight: 600 !important;
color: var(--base-color-brand--blue) !important;
opacity: 0.3 !important; background: transparent !important;
display: flex !important; border-radius: 50% !important;
cursor: pointer !important; justify-content: center !important;
align-items: center !important;
}
.swiper-pagination-bullet.swiper-pagination-bullet-active {
opacity: 1 !important;
color: var(--base-color-brand--blue-dark) !important;
}
.swiper-slide { height: auto !important; }
</style>

Replace var(--base-color-brand--blue) and var(--base-color-brand--blue-dark) with the client's brand colour variables or hard-coded values.


Initialisation script (before </body>)

Add to Page Settings → Custom Code → Before </body> tag:

var swiper = new Swiper("#products-swiper", {
a11y: false,
grabCursor: true,
slidesPerView: 3,
spaceBetween: 25,
navigation: {
nextEl: ".products-right-button",
prevEl: ".products-left-button",
},
pagination: {
el: ".products_pagination",
clickable: true,
renderBullet: function (index, className) {
return '<span class="' + className + '">' + (index + 1) + "</span>";
},
},
breakpoints: {
0: { slidesPerView: 1.1, spaceBetween: 20 },
767: { slidesPerView: 1.5, spaceBetween: 24 },
988: { slidesPerView: 2.5, spaceBetween: 24 },
},
});

Breakpoints

ViewportslidesPerViewEffect
0–766px (mobile)1.1Single card with peek of next card
767–987px (tablet)1.5One and a half cards visible
988–1199px2.5Two and a half cards visible
1200px+ (desktop)3Three full cards

The 0.1 / 0.5 fractional values create a "peek" effect that signals scrollability.


Reuse notes

  • Rename products-swiper, products-left-button, products-right-button, and products_pagination per layout to avoid conflicts when multiple Swiper instances are on the same page.
  • Keep the init script in one place per page.
  • Adjust slidesPerView and spaceBetween per design — the values above are a tested starting point.
  • Works for services, testimonials, or feature carousels: only the slide content and breakpoint values change.