Recently I was using swiper.js to make a slide show. One of the features that was requested was to have pagination with dots on the bottom and a fraction counter in the top right like Instagram. Unfortunately it turns out swiper can't do multiple pagination. The good thing is that it's api lets you make it possible.

See the Pen Swiperjs with dual pagination by James (@jamcgrath) on CodePen.

First thing to do is follow the [swiper documentation]([https://swiperjs.com/get-started#add-swiper-html-layout](https://swiperjs.com/get-started#add-swiper-html-layout)) and setup exactly like in the examples.

In the markup I deleted <div class="swiper-scrollbar"></div> and added <div id="fraction" class="swiper-fraction"></div> after <div class="swiper-container"> .

<div class="swiper-container">
    <div id="fraction" class="swiper-fraction"></div>
    <!-- Additional required wrapper -->
    <div class="swiper-wrapper">
      <!-- Slides -->
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=1" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=2" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=3" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=4" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=5" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=6" width="600" height="600">
      </div>
      <div class="swiper-slide">
        <img src="https://picsum.photos/600?random=7" width="600" height="600">
      </div>
    </div>
    <!-- If we need pagination -->
    <div class="swiper-pagination"></div>

    <!-- If we need navigation buttons -->
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>
  </div>

The next thing to do is to style the fraction counter.

.swiper-fraction {
  background: rgba(0, 0, 0, 0.5);
  color: white;
  position: absolute;
  right: 1em;
  top: 1em;
  z-index: 10;
  padding: 10px 15px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: bold;
}

Now it's time to set up the fraction with js. The plan is to get all the elements with the swiper-slide class and count them to determine what the bottom number of the fraction should be. Then insert it into the fraction div so it will be 1/ .swiper-slide count

const fraction = document.getElementById("fraction");
const slides = document.querySelectorAll(".swiper-slide");
const slideCount = slides.length;
fraction.textContent = `1 / ${slideCount}`;

Now that the markup is handled, it's time to initialize swiper like the documentation and add an event listener to it that will update the fraction counter.

const swiper = new Swiper(".swiper-container", {
  // If we need pagination
  pagination: {
    el: ".swiper-pagination"
  },

  // Navigation arrows
  navigation: {
    nextEl: ".swiper-button-next",
    prevEl: ".swiper-button-prev"
  },

  on: {
    slideChange: () => {
      fraction.textContent = `${swiper.realIndex + 1} / ${slideCount}`;
    }
  }
});

In the on slideChange, the function is updating the textContent of the fraction div by getting the index of the current slide from swiper using the realIndex property and adding 1 to it because the index starts at 0.

As a bonus let's move the navigation dots below the image. This is some straight forward css. On the swiper-container we'll add padding to the bottom of the element and set the box-sizing to content-box. The box-sizing in short will add the padding outside the content area of the div. This may not be needed if you are not doing a global box model setting.

.swiper-container {
  padding-bottom: 30px;
  box-sizing: content-box;
}

That's it. Now we got a swiper instance that has "multiple pagination".