Build a No Plugin Image Slider in WordPress

Just want the code? Here’s the git repository

If you want to maintain total control over the code and design choices on your site, it’s important to use as few plugins as possible! Creating your own components not only gives you total control, but it allows you to keep your http requests low, and reduces the amount of data required to load your site.

A popular component on many websites is the Hero Slider. These are great for supporting your branding and quickly conveying bits of information, like upcoming events, sales, mailing list forms, and so on. They also tend to be extremely bulky plugins, as they load boatloads of css and javascript in order to support their many customizations.

There are many ways to create your own, and a number of great libraries like swiper and tinyslider, but the most efficient way is to build your own! Personally, I like to have a library of my own components, that way I can easily re-use and modify them for quickly setting up new sites and being able to easily tailor and extend them to add the required form and functionality.

So enough rambling, let’s start working on our no plugin image slider! I’m going to demonstrate the barebones HTML, CSS, and Javascript required, as well as how to implement this in WordPress.

Step 1: The Structure

First, lets set up the basic HTML we’ll need to accomplish this. We’ll need two divs, one to act as the wrapper, and one to contain each of our slides. The first div will hide the overflow with a set width and overflow hidden, while the second will have width:auto; and overflow the screen to contain each of our slides. We can add a couple of demo slides inside as well.

<div class="slider-wrapper">
      <div id="slider" class="slider transition">
        <div class="slide">1 <img src="img.jpg" /></div>
        <div class="slide">2 <img src="img2.jpg" /></div>
        <div class="slide">3 <img src="img3.jpg" /></div>
      </div>
</div>

Now for the styling. The width of the slider-wrapper is up to you, but you should set your .slide class to the same width in order to have each one fill the width of the container div. I’ve added borders to the .slider and .slide classes just so that you can verify the width of the elements while building out the slider. I’ve also set the initial transform of the .slider to transform:translateX(-90vw), we’ll discuss that in a second.

 .slider-wrapper {
        width: 90vw;
        margin: auto;
        overflow: hidden;
      }
      .slider {
        width: auto;
        height: 80vh;
        margin: auto;
        display: flex;

        border: 2px solid black;
        transform: translateX(-90vw);
      }
      .slide {
        width: 90vw;
        background: grey;
        height: 30vh;
        border: 1px solid red;
        flex: 1 0 auto;
      }

  .transition {
        -webkit-transition: 0.3s all;
        -moz-transition: 0.3s all;
        -o-transition: 0.3s all;
        transition: 0.3s all;
      }
      .notransition {
        -webkit-transition: none !important;
        -moz-transition: none !important;
        -o-transition: none !important;
        transition: none !important;
      }

Great! Now we need some buttons.

 <div class="slider-controls">
      <p id="slider-left" onclick="left()">left</p>
      <p id="slider-right" onclick="right()">right</p>
    </div>

You can swap out ‘left’ and ‘right’ for icons, carats, or whatever makes you feel good.

Step 2: The JavaScript

Okay so we have our structure set up, now we need to make it move! We’ll need to access some of the HTML elements we just set up, so lets grab them first

var slideRight = document.getElementById("slider-right");
var slideLeft = document.getElementById("slider-left");
var theSlider = document.getElementById("slider");
var slides = document.getElementsByClassName("slide");

and we’ll need some additional variables to help us keep track of a few things

//get number of slides
 var count = slides.length;
//set your start position to 2
 var position = 2;

The count will allow us to track our position among the number of slides we’ve created, and we’re setting our start position to 2 so that we start from the second slide. Why?

Well, in order to get a smooth, infinite scroll from the last slide to the first slide and vice versa, we’re going to need to duplicate our first and last slides and append them to opposite sides of our slider.

With duplicates, we can animate our transition back to the first and last slides, remove our transition effect, jump back to the actual start/end of the slider, and then re-enable our transition so that we can continue on with our smooth slide movement.

So, lets append a duplicate of our first slide to the end, and a duplicate of our last slide to the front.

//get the last slide first so that you aren't copying the first slide twice
 var newChild = slides[slides.length - 1];
//append copy of last slide to front, and copy of first slide to end
 theSlider.innerHTML =
     newChild.outerHTML + theSlider.innerHTML + slides[0].outerHTML;

Now we need to get things moving! We’ll need to write two functions to handle movement of the slides to the left and right. Lets write our right movement function first.

   function right() {
        console.log("position: " + position + " count: " + count);

        if (position <= count) {
          console.log("right, position<=count");

          theSlider.style.transform = `translateX(-${9 * position}0vw)`;
          position++;
        } else if (position > count) {
          console.log("right, position >count");

          theSlider.style.transform = `translateX(-${9 * position}0vw)`;
          setTimeout(function () {
            theSlider.classList.remove("transition");
            theSlider.classList.add("notransition");

            theSlider.style.transform = "translateX(-90vw)";
          }, 300);

          setTimeout(function () {
            theSlider.classList.add("transition");
            theSlider.classList.remove("notransition");
          }, 600);
          position = 2;
        }
        console.log("position: " + position + " count: " + count);
        return position;
      }

I added some console.logs for debugging, so that you can check that your code is running when expected. You can remove those if everything’s working!

We have an if/else statement to handle two scenarios, when position <= count and what to do otherwise. this will allow us to handle normal movement, as well as transitioning from the end of the slider, back to the front of the slider, seamlessly.

Regular movement is straightforward, but the seamless transition is where it gets fun! We’re using two setTimeouts, one at 300ms and one a 600ms, (this mirrors the transition speed, so adjust if you set a longer or shorter transition) in order to allow our slider to transition to the duplicate at the end, remove its transition style, jump back to the front of the slider, and then re-enable transitions. Viola!

We’ll do the same thing for our left movement, but for the opposite direction

 function left() {
        if (position > 2) {
          console.log("left, position >=2");
          position--;
          if (position == 1) {
            theSlider.style.transform = `translateX(0vw)`;
            position = slides.length - 2;
            setTimeout(function () {
              theSlider.classList.remove("transition");
              theSlider.classList.add("notransition");
              theSlider.style.transform = `translateX(-${9 * position}0vw)`;
            }, 300);

            setTimeout(function () {
              theSlider.classList.add("transition");
              theSlider.classList.remove("notransition");
            }, 600);
          } else {
            theSlider.style.transform = `translateX(-${9 * position}0vw)`;
          }
        } else if (position < 2) {
          console.log("left, position <=2");
          position = slides.length - 2;
          theSlider.style.transform = `translateX(0vw)`;
          setTimeout(function () {
            theSlider.classList.remove("transition");
            theSlider.classList.add("notransition");

            console.log(position);
            theSlider.style.transform = `translateX(-${9 * position}0vw)`;
          }, 300);

          setTimeout(function () {
            theSlider.classList.add("transition");
            theSlider.classList.remove("notransition");
          }, 600);
        } else if (position == 2) {
          position--;
          theSlider.style.transform = `translateX(-${9 * position}0vw)`;
        }
        console.log("position: " + position + " count: " + count);
        lastClicked = left;
        return position, lastClicked;
      }

Now just set an Interval on the right function if you want automatic transitioning, and you’re good to go!

Step 3: WordPress

With Advanced Custom Fields Pro, you can make a really nice, dynamic slider! I’ve included an export of my field group in the repo if you’d like to implement it. I have things grouped for future extensibility, so I can add new groups with different fields/styles down the road.

Your CSS and Javascript will be largely the same, but with a repeater you can dynamically add and remove slides, which will result in an easy to use back-end interface which can be used on any page. The best way to make this easily re-usable would be to create a template part, and then simply use get_template_part() to implement it on the page templates you want it to appear on.

Need some personal help?
Drop us a line!