Sliders That Don't Suck: Why Splide Is the Secret Weapon Your Webflow Needs

8.28.2024
by
Web Bae

In this post I'll talk a bit about Splide, a Javascript library (with full typescript support), for building sliders. The associated cloneable has a bunch of examples you can use in your project too! Use the examples to add sliders to your Webflow projects in minutes.

DEMO/CLONE
TUTORIAL
CODE

See the Pen Splide Slider by learyjk (@learyjk) on CodePen.

Acknowledgements:

OK so sliders—those little carousels of content that, for better or worse, have become a staple in web design. They’re like the cilantro of web development: some folks can’t get enough, while others are genetically pre-disposed to just hate the stuff forever without compromise. Regardless of your stance, I'm willing to bet you've got a client or two who wants one (or fifty) on their site. Since I've come across them so many times now, and I'm always getting help requests to build them, I figured I'd take some time and space here to teach you how to build one with the popular JS library Splide, and also keep a library in this cloneable of different variations you can pull from for all your future needs.

So let me tell you about Splide. This little library has wormed its way into my developer heart, and for good reason. Splide is lean—27kB lean. It’s dependency-free, which is the web dev equivalent of finding a parking spot in San Francisco on a Saturday. And it’s written in TypeScript. For those who know, you know.

I get it—SwiperJS is the slider king around these parts. The Webflow community has practically adopted it as the official slider of choice, and I’m not here to dethrone it. But let’s talk about why Splide is the underdog you didn’t know you needed. First off, it plays nice with CSS relative units. That might sound like a small thing, but when Swiper is locked in pixel purgatory, you start to appreciate the freedom of working with percentages and ems.

And syncing multiple sliders? Splide just seems to have its act together. Swiper, on the other hand, sometimes feels like it’s been out partying the night before and is trying to pull itself together for a 9 AM meeting. In my experience ever since version 10, it’s a little wonky, especially when you’re dealing with different slidesPerView settings.

But wait, there’s more! Splide seems to have a better relationship with Webflow’s lazy loading and out-of-view slides, which is a big deal if you care about page performance and UX (and you should). Plus, it ships with way less CSS than Swiper. You ever open Swiper’s stylesheet and wonder if you accidentally clicked on a novella instead of a CSS file? Yeah, Splide keeps it concise. Both Swiper and Splide have options of importing only the required code via modules, but I almost always see Webflower folks just importing the whole dang thing because it's easier that way (and that's how pretty much every tutorial online seems to do it - and everyone is just copying each other let's be real).

Oh, and did I mention the auto-scroll extension? If you’re dying to add a marquee effect that doesn’t feel like my 1999 Angelfire pokémon tribute website, Splide’s got you covered. Again since version 10 or so, I haven't seen this work with Swiper.

But, and this is a big but, there’s one thing about Splide that drives me up the wall: the is-active class. It’s like that one friend who’s always late—no matter how many times you tell them the party starts at 7, they show up at 7:30. By default, the is-active class doesn’t swap until the slide transition is complete, making your CSS transitions feel laggy, like they’re dragging their feet. And as much as I despise laggy animations, it's an easy fix with the updateOnMove option.

But enough talk. Let’s build this slider. If you’re itching to get started, check out the CodePen demo and let’s get into it.

A CodePen Example of a Baisc Splide Slider

First things first, we need to get Splide running on CodePen. It’s as simple as adding the Splide CSS and JavaScript to your project. (if you're getting used to CodePen, check the pen settings for imported JS).

<link href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>

With that in place, let’s set up the HTML structure. Here’s how it looks:

<div class="splide bae-override">
  <div class="splide__track bae-override">
    <div class="splide__list bae-override">
      <div class="splide__slide bae-override">
        <img src="your-image-here.jpg" alt="Slide 1" class="image">
      </div>
      <!-- Add more slides as needed -->
    </div>
  </div>
  <div class="splide__controls">
    <ul class="splide__pagination bae-override"></ul>
    <div class="splide__arrows">
      <button class="splide__arrow--prev">Prev</button>
      <button class="splide__arrow--next">Next</button>
    </div>
  </div>
</div>

You’ll notice the .bae-override class sprinkled everywhere—that’s my little custom combo class to override Splide’s default styles without going full ham on the !important hammer. Trust me, you want to keep those required Splide classes intact and add your own combo classes to keep things manageable. This way, you can drop multiple sliders into the same project without tearing your hair out trying to wrangle CSS conflicts.

Overriding Default CSS with Combo Classes

Let's add some of our own styling now:

.splide__slide.bae-override {
  position: relative;
  background-color: #fff;
  border-radius: 0.5rem;
  padding: 0.5rem;
  filter: brightness(80%);
  transition: filter 0.3s, transform 0.3s;
}

.splide__slide.bae-override.is-active {
  filter: brightness(100%);
  transform: scale(1.1);
}

.splide__pagination.bae-override {
  flex: 1;
  justify-content: start;
  align-items: center;
  margin-bottom: 0;
  padding: 0;
  display: flex;
  position: relative;
}

.splide__pagination__page.bae-override {
  background: #feffff;
  border: 0;
  border-radius: 50%;
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin: 3px;
  opacity: 1;
  padding: 0;
  position: relative;
  transition: transform 0.2s ease;
}

.splide__pagination__page.bae-override.is-active {
  background: #e5693b;
  transform: scale(1.4);
}

This CSS gives each slide a nice, clean look with a subtle brightness effect and a smooth scale-up transition when it becomes active. Splide's default position for splide__pagination is absolute, so here we override that with relative and also provide our owns styles for the pagination dot and the active dot.

Getting the Slider Moving

Now let’s bring this slider to life. We need to initialize Splide using JavaScript. Here’s the basic setup:

const splide = new Splide(".splide", {
  type: "loop",
  perPage: 4,
  focus: "center",
  perMove: 1,
  gap: "3rem",
  pagination: true,
  padding: "2rem",
  classes: {
    pagination: "splide__pagination bae-override",
    page: "splide__pagination__page bae-override"
  },
  breakpoints: {
    991: {
      perPage: 3
    },
    478: {
      gap: "2rem",
      padding: "4rem",
      perPage: 1
    }
  }
});
splide.mount();

We’re setting up a looped slider with four slides visible at a time, and a focus on the center slide. The focus property makes it so that the active slide will be displayed in the center of the slider. The classes property allows us to tell Splide that we are using the bae-override combo class on top of the default Splide pagination classes splide__pagination (the container) and splide__ pagination__page (the dot).

Fun fact - the pagination dots are generated programatically. What does this mean? It means that on initialization, there really shouldn't be any HTML elements inside of the splide__pagination container. Check the CodePen - nothing inside of that div. In Webflow, we often like to style our classes using the styles panel, which requires those elements to exist on the page already. Be careful here! If they are on the page, you might run into some odd sliders with duplicate pagination dots, I'm speaking form experience here! If you want to style these visually in Webflow, I like to do so on the page (better yet in the style guide), and then either leave it in the style guide or use the CSS Preview to copy/paste the generated CSS into the page settings.

OK enough of that. If you run the slider now, you'll see that one thing I can't stand... the delayed CSS transition.

Fixing the is-active Class Transition Issue

Remember that annoying is-active class delay I mentioned? Let’s fix it with the updateOnMove property. We want the class to change as soon as the slide starts moving, not when it finishes. Here's the final code:

const splide = new Splide(".splide", {
  type: "loop",
  updateOnMove: true,
  perPage: 4,
  focus: "center",
  perMove: 1,
  gap: "3rem",
  pagination: true,
  padding: "2rem",
  classes: {
    pagination: "splide__pagination bae-override",
    page: "splide__pagination__page bae-override"
  },
  breakpoints: {
    991: {
      perPage: 3
    },
    478: {
      gap: "2rem",
      padding: "4rem",
      perPage: 1
    }
  }
});
splide.mount();

Boom. I feel so much better now.