Intro

In this tutorial, I’ll teach you how to create an animated slider yourself, using the Glide.js JavaScript library, Intersection Observer API and a number of CSS transitions. Such a slider, can be further expanded upon with Advanced Custom Fields or placed within a custom shortcode. Thus being a part of your WordPress theme.

🎯 What is Glide.js?

Glide.js is a lightweight, flexible, and dependency-free JavaScript library for building sliders and carousels. It’s designed for modern browsers and mobile-first design, offering smooth transitions and easy configuration. With just a few lines of code, you can create sliders that support autoplay, touch/swipe navigation, and various transition effects.

💡 Why Use an Animated Slider?

Animated sliders are a powerful way to enhance your website’s visual appeal and user engagement. Here’s why they’re often used:

  • Draw attention: Motion catches the eye, helping highlight key messages, promotions, or featured content.
  • Save space: Sliders let you show multiple pieces of content in a limited area—perfect for headers or galleries.
  • Improve storytelling: They guide users through content in a controlled, visual sequence.
  • Engage users: Smooth animations feel modern and dynamic, giving the site a polished and interactive feel.

👀 When to Use (and Not Use) a Slider

Good for:

  • Product showcases
  • Portfolio pieces
  • Hero sections with multiple messages
  • Testimonials

Use with care if:

  • You have too much critical content (it might get ignored in a fast autoplay)
  • Performance is a concern (too many images or scripts)

Tutorial

I’ll provide you with a basic idea and examples of HTML code in that section, explaining parts of the final HTML / CSS only. You’ll need to investigate the whole source code provided at the bottom of the tutorial to carry over all of these changes and recreate the slider.

Prerequisities

To start with the tutorial, we need to load the Glide.js library first, place the following links in the HEAD of your HTML document:

<link rel='stylesheet' id='glide-css' href='https://glidejs.com/css/app.css?ver=6.7.2' media='all' />
<script src="https://cdn.jsdelivr.net/npm/@glidejs/glide?ver=6.7.2" id="glide-js"></script>

HTML code

Now then, we need to set-up the Glide.js HTML code, according to the library’s documentation the markup is pretty simple:

<div class="glide__bullets" data-glide-el="controls[nav]">
   <button class="glide__bullet" data-glide-dir="=0"> Slide 1 </button>
   <button class="glide__bullet" data-glide-dir="=1"> Slide 2 </button>
   <button class="glide__bullet" data-glide-dir="=2"> Slide 3 </button>
</div>
<div class="glide glide--67e296fd5424b">
   <div class="glide__track" data-glide-el="track">
      <ul class="glide__slides">
         <li class="glide__slide">0</li>
         <li class="glide__slide">1</li>
         <li class="glide__slide">2</li>
      </ul>
   </div>
</div>

This part is pretty self explanatory, I guess. We have a container for the buttons at the top, and a wrapper for the slides at the bottom. We can now expand upon the example and and more content to it next. The whole source code, can be downloaded at the bottom of this guide.

CSS Code

Now then, we want to make sure that each slide can contain 3 elements inside, at least and that each element animates from bottom to top (i.e. fade-up animation). We’ll have to expand our example and introduce an inner elements to each slide first. Lets’ place 3 such elements directly inside our .glide__slide list element.

<div class="glide__slide--inner glide__slide--inner-1">
   <strong>Lorem:</strong>
   <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et           dolore magna aliqua.
      Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo                   consequat.
      Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
   </p>
</div>

To make sure all elements fit in the screen, we’ll need to make sure that each slide displays as a grid element, say:

.glide--67e296fd5424b .glide__slide {
   display: grid;
   grid-template-columns: auto auto auto;
   grid-gap: 10px;
}

Similarly, we want to apply some sort of CSS animations to the elements inside each slide, say: we want to make sure each inner element has a slight padding applied to it, a box shadow, and an initial opacity of 0, which we’ll change to 1 later on, via JavaScript. The transition part uses, the default transition effect, applied to the opacity change. 

.glide--67e296fd5424b .glide__slide--inner {
   padding-top: 40px;
   padding-right: 50px;
   padding-bottom: 40px;
   padding-left: 50px;
   box-shadow: 0px 25px 25px 0px #E8E8E8;
   margin: 50px 15px;
   border-radius: 30px;
   opacity: 0;
   transition: opacity 0.6s ease-in, box-shadow 0.3s ease;
}
.glide--67e296fd5424b .glide__slide--inner.animated {
   animation: fl-fade-up 0.6s ease;
   -webkit-animation: fl-fade-up 0.6s ease;
   opacity: 1;
}

Now then, the slide with the animated class attached to it uses a custom animation, which we have to create the keyframes for first. The code is pretty simple. The elements to which the animation is applied move from bottom to top and its opacity changes from 0 to 1 upon the animation completion.

@keyframes fl-fade-up {
  from {
     opacity: 0;
     -webkit-transform: translate3d(0, 50%, 0);
     transform: translate3d(0, 50%, 0);
  }

  to {
     opacity: 1;
     -webkit-transform: translate3d(0, 0, 0);
     transform: translate3d(0, 0, 0);
  }
}

JavaScript code

As you may have already figured out we’ll use a trick to apply the fade up animation on our inner elements. And to do so, we’ll use the Intersection Observer API, which is a great way to figure out whether or not any given element is visible. Per the documentation from the developer.mozilla.com:

“The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.”

Our code is pretty simple, so I’ll paste the whole code here:

document.addEventListener('DOMContentLoaded', function (event) {
      var glide = new Glide('.glide--67e296fd5424b', {
         type: 'carousel',
         startAt: 0,
         perView: 1,
         focusAt: 'center'
},).mount();

const slides = document.querySelectorAll(".glide__slide--inner");
const observer = new IntersectionObserver(
     (entries) => {
        entries.forEach((entry) => {
        if (entry.isIntersecting) {
        entry.target.classList.add("animated");
     }
   });
   },
   {  threshold: 0.5  }
);

slides.forEach((slide) => {
    observer.observe(slide);
  });
});

Here, we’re doing a number of things:

  1. First, we’re assuring that the whole DOM has loaded. The script won’t start until we would have loaded the whole “HTML code”.
  2. Then, we’re instantiating the glide.js carousel, using a custom set of arguments.
  3. Finally, we’re using the Intersection Observer, applied to each element with the .glide__slide–inner class in it.
  4. Our threshold arguments mean, that the function will fire if at least 50% of our element is visible.

In our case, this will fire immediately on the first slider (as all of the elements of the first slider are visible by default). Then the animation will apply when we change the slide of our slider. As each slide but the first one is hidden by default 🙂

End Result

  • Lorem:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Ipsum:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Dolor:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

  • Lorem:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Ipsum:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Dolor:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

  • Lorem:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Ipsum:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    Dolor:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Notes

Based on my research, the code may be buggy in the numerous Safari browsers. I am yet to find a solution to that problem. Needless to say, that’s a common problem across that platform. You may want to disable the Intersection observer for the Safari browser, thus disabling the fade up animation, say via the following true / false statement:

var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

if( !isSafari ) {
slides.forEach((slide) => {
     observer.observe(slide);
  });
}

Part 2

In the second part of the tutorial, coming up next week – I’ll teach you how to add the Back End managment of the plugin, making it fully customizable and editable – using Advanced Custom Fields Pro.

Useful Links