A11Y Slider

Library for simple and accessible sliders.

Single Item

  • 1
  • 2
  • 3
  • 4
  • 5
const slider = new A11YSlider(document.querySelector(".slider"));
.slider {
  display: flex;
}

.slider > * {
  width: 100%;
  flex: 0 0 auto;
}

Multiple Items

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
const slider = new A11YSlider(document.querySelector(".slider"));
.slider {
  display: flex;
}

.slider > * {
  width: 25%;
  flex: 0 0 auto;
}

Items with JS

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const slider = new A11YSlider(document.querySelector(".slider"), {
  slidesToShow: 2
});

Responsive Pure CSS

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const slider = new A11YSlider(document.querySelector(".slider"));
.slider {
  display: flex;
}

.slider > * {
  width: 100%;
  flex: 0 0 auto;
}

@media (min-width: 768px) {
  .slider > * {
    width: 50%;
  }
}

@media (min-width: 960px) {
  .slider > * {
    width: 33.3333%;
  }
}

@media (min-width: 1280px) {
  .slider > * {
    width: 25%;
  }
}

Responsive Options

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const slider = new A11YSlider(document.querySelector(".slider"), {
  slidesToShow: 1,
  arrows: true, // arrows enabled 767px and down
  dots: false,
  responsive: {
    768: {
      slidesToShow: 2,
      arrows: false
    },
    960: {
      disable: true // slider disabled 960px to 1279px
    },
    1280: {
      disable: false,
      slidesToShow: 4,
      dots: true // dots enabled 1280px and up
    }
  }
});

Autoplay

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const slider = new A11YSlider(document.querySelector(".slider"), {
  autoplay: true,
  autoplaySpeed: 2500
});
.slider {
  display: flex;
}

.slider > * {
  width: 100%;
  flex: 0 0 auto;
}

Synced Sliders

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const sliderEl = document.querySelector(".slider");
const sliderEl2 = document.querySelector(".slider-2");
const slider = new A11YSlider(sliderEl);
const slider2 = new A11YSlider(sliderEl2);

sliderEl.addEventListener("beforeChange", function(e) {
  // Get next element
  const nextSlide = e.detail.nextSlide;
  // Get index of the next element
  const nextSlideIndex = Array.from(nextSlide.parentNode.children).indexOf(
    nextSlide
  );
  // Tell 2nd slider to move to slide element based off index
  slider2.scrollToSlide(nextSlideIndex);
});

Install

Using npm:

npm install a11y-slider

Using browser:

<!-- In the <head> -->
<link rel="stylesheet" href="//unpkg.com/a11y-slider@latest/dist/a11y-slider.css" />

<!-- End of <body> -->
<script src="//unpkg.com/a11y-slider@latest/dist/a11y-slider.js"></script>

Usage

A11YSlider works by using CSS scroll snapping. You can generate a slider by creating an overflowed container and then setting widths all via CSS. Media queries in your CSS will also update the slider.

<style>
  .slider {
    display: flex;
  }

  .slider > * {
    width: 100%;
    flex: 0 0 auto;
  }
</style>

<ul class="slider">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

<script>
  const slider = new A11YSlider(document.querySelector('.slider'), {
    adaptiveHeight: true,
    dots: false
  });
</script>

A11YSlider(element, options)

The element is the targeted slider element. The options is an optional parameter. See options for more info.

Note: A11YSlider only runs if needed! If A11YSlider detects that all slides are already visible in the container then it will not run.

Options

OptionTypeDescription
containerBooleanDefault: true
Adds a container element around the slider
arrowsBooleanDefault: true
Enables prev/next button
prevArrowNode | NodeListDefault: <button>
Button to trigger previous slide. A11YSlider will generate one by default. Can be one or multiple HTML elements.
nextArrowNode | NodeListDefault: <button>
Button to trigger next slide. A11YSlider will generate one by default. Can be one or multiple HTML elements.
dotsBooleanDefault: true
Generate navigation dots
adaptiveHeightBooleanDefault: false
Height of slider container changes according to each slide's height
skipBtnBooleanDefault: true
Adds a skip button before the slider for a11y devices (Can be seen by tabbing)
slidesToShowNumber | NullDefault: null
The total number of items to be shown. By default A11YSlider will work by default based off your CSS styling. This option hardcodes the width into the HTML for you.
autoplayBooleanDefault: false
Enables the automatic change of slides
autoplaySpeedNumberDefault: 4000
Time between slide changes when autoplay is enabled (milliseconds)
autoplayHoverPauseBooleanDefault: true
If autoplay is enabled then pause when the slider is hovered
centerModeBooleanDefault: false
(EXPERIMENTAL) Makes the center slide active
infiniteBooleanDefault: true
Makes the slider infinitely loop
disableBooleanDefault: false
Disables the slider
responsiveObject | NullDefault: null
Define options for different viewport widths. See responsive example
customPagingFunction | NullDefault: null
Define your own custom dots template
swipeBooleanDefault: true
Enable swiping

Responsive Option Example

You can have different options per specified viewport width. This behaves like CSS min-width media queries. Your initial options outside of the responsive object will work from your lowest specified viewport and down.

const slider = new A11YSlider(document.querySelector('.slider'), {
  slidesToShow: 1,
  arrows: true, // arrows enabled 767px and down
  dots: false,
  responsive: {
    768: {
      slidesToShow: 2,
      arrows: false
    },
    960: {
      disable: true // slider disabled 960px to 1279px
    },
    1280: {
      disable: false,
      slidesToShow: 4,
      dots: true // dots enabled 1280px and up
    }
  }
});

Custom Paging Example

If you would like your own custom HTML for each dot you can pass in your own function. It must return a string and then this function will be called to create HTML for each individual dot. Note that dots will still be wrapped in a <ul>.

const slider = new A11YSlider(document.querySelector('.slider'), {
  dots: true,
  customPaging: function(index, a11ySlider) {
      return '<button class="mycustombtn">' + index + '</button>';
  }
});

Will output to:

<ul class="a11y-slider-dots">
  <li><button class="mycustombtn">0</button></li>
  <li><button class="mycustombtn">1</button></li>
  <li><button class="mycustombtn">2</button></li>
  <li><button class="mycustombtn">3</button></li>
</ul>

Methods

// Example use of the 'scrollToSlide' method.
// Scrolls to the 3rd slide (0-based index)
slider.scrollToSlide(2);
MethodArgumentsDescription
scrollToSlideNumber | ElementScrolls slider to specified slide index (0-based) or slide element
updateOptionsObjectEnter new set of options (reloads slider)
refreshHeightSets height of slider to height of the current active slide
destroyRemoves everything that the A11YSlider created in the DOM

Events

// Example use of the 'afterChange' event
const sliderEl = document.querySelector('.slider');

sliderEl.addEventListener('afterChange', function(e) {
  console.log(e.detail.currentSlide);
});

const slider = new A11YSlider(sliderEl, {
    infinite: true
});
EventDetailDescription
inita11ysliderFires after slider initialization
beforeChangecurrentSlide, nextSlide, a11ysliderFires before slide change
afterChangecurrentSlide, a11ysliderFires after slide change
autoplayStartcurrentSlide, a11ysliderFires when autoplay starts
autoplayStopcurrentSlide, a11ysliderFires when autoplay stops
destroya11ysliderFires after the slider is destroyed

Events listeners should be added before initializing the slider if possible. For example init will require it.

Browser support

A11YSlider works on all modern browsers including IE11. See notes for some caveats.

Notes

  • Non-modern browsers that doesn't support ScrollToOptions will not have smooth scrolling when switching slides. A polyfill like smoothscroll can be used to fix this.

Todo

  • Examples
  • Look into not removing width style from slides
  • Make autoprefix run automatically
  • Better resize throttling
  • Look into enabling useCapture for scroll events to prevent window events