Creating an Accessible Swiper Slider with Custom Play/Pause Button and Enhanced Accessibility Features

In today’s digital landscape, ensuring that web content is accessible to all users, including those with disabilities, is paramount. Sliders are a popular web design element, but they often fall short when it comes to accessibility. In this guide, we’ll walk you through the steps to create an accessible Swiper slider, complete with a custom play/pause button and tailored accessibility enhancements. By the end of this tutorial, you’ll be equipped with the knowledge to deliver a seamless and inclusive user experience for everyone visiting your website. Let’s dive in!

1. HTML Structure

First, let’s set up the HTML structure for our Swiper slider:

<div id="slider-id" class="swiper dsb-slider">
    <div class="swiper-wrapper">
        <!-- Swiper Slide 1 -->
        <div class="swiper-slide">
            <img src="path_to_image1.jpg" alt="Description for Image 1">
            <div class="carousel-caption">
                <p class="lead">Caption for Image 1</p>
            </div>
            <div class="slide-caption">
                <h2 class="heading" tabindex="0">Heading for Slide 1</h2>
                <p class="lead">Description for Slide 1</p>
                <a class="button" href="#">Button Text</a>
            </div>
        </div>
        <!-- Add more slides as needed -->
    </div>
    <div class="swiper-pagination"></div>
    <button class="dsb-button-control" aria-pressed="false">
        <span class="screen-reader-text">Pause</span>
        <span class="dashicons dashicons-controls-pause"></span>
    </button>
</div>

2. JavaScript Implementation

Now, let’s move on to the JavaScript part:

2.1 Swiper Configuration

First, we’ll define the Swiper configuration:

let args = {
    loop: true,
    speed: 1000,
    autoplay: {
        delay: 5000,
    },
    pagination: {
        el: '.swiper-pagination',
        clickable: true,
    },
    on: {
        afterInit: function (dsb_slider) {
            // Accessibility functions will be added here
        },
    }
};

2.2 Accessibility Enhancements

Inside the afterInit function, we’ll add our accessibility enhancements:

on: {
    afterInit: function (dsb_slider) {
        // Jump to the current active bullet on tab
        const button = document.querySelectorAll('.button');
        button.forEach(function (item) {
            item.addEventListener('keydown', function (event) {
                if (event.keyCode === 9) {
                    event.preventDefault();
                    const activeBullet = document.querySelector('.swiper-pagination-bullet-active');
                    activeBullet.focus();
                }
            });
        });

        // Space key to click pagination bullet and focus on h2 when clicked
        const pagination = document.querySelectorAll('.swiper-pagination-bullet');
        pagination.forEach(function (item, index) {
            item.addEventListener('keydown', function (event) {
                if (event.keyCode === 32) {
                    event.preventDefault();
                    item.click();
                }
            });
            item.addEventListener('click', function() {
                const h2Element = dsb_slider.slides[index].querySelector('h2');
                if (h2Element) {
                    h2Element.focus();
                }
            });
        });

        // Play/Pause control button
        const controlBtn = document.querySelector('.dsb-button-control');
        controlBtn.addEventListener('click', function () {
            if (this.getAttribute('aria-pressed') === 'false') {
                dsb_slider.autoplay.stop();
                this.querySelector('.screen-reader-text').textContent = 'Play';
                this.querySelector('.dashicons').classList.remove('dashicons-controls-pause');
                this.querySelector('.dashicons').classList.add('dashicons-controls-play');
                this.setAttribute('aria-pressed', 'true');
            } else {
                dsb_slider.autoplay.start();
                this.querySelector('.screen-reader-text').textContent = 'Pause';
                this.querySelector('.dashicons').classList.remove('dashicons-controls-play');
                this.querySelector('.dashicons').classList.add('dashicons-controls-pause');
                this.setAttribute('aria-pressed', 'false');
            }
        });
    },
}

2.3 Initialize Swiper

Finally, we’ll initialize the Swiper slider:

const dsb_slider = new Swiper('#slider-id', args);

Full code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Accessible Swiper Slider with Custom Play/Pause & Enhancements</title>
    <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
    <style>
    :root {
        --swiper-pagination-bullet-horizontal-gap: 5px;
    }

    .dsb-slider .slide-caption {
        background-color: rgba(255,255,255,.95);
        padding: 2em;
        text-align: left;
        overflow: visible;
        left: 0%;
        right: 0%;
        text-shadow: none;
        bottom: 0;
        top: unset;
        position: absolute;
        width: 33%;
    }
    .dsb-slider .swiper-pagination {
        position: absolute;
        left: 29%;
        z-index: 15;
        width: 60%;
        padding-left: 0;
        margin-left: -30%;
        text-align: center;
        list-style: none;
        bottom: 10px;
        top: unset;
    }
    .dsb-slider .swiper-pagination-bullet.dsb-pagination-bullet-active {
        background-color: black;
    }
    .dsb-slider .swiper-pagination-bullet {
        background-color: #747474;
        opacity: 1;
    }
    .dsb-slider .swiper-pagination-bullet:focus {
        outline: 1px solid black;
        outline-offset: 2px;
    }
    .dsb-slider .button {
        background-color: #FF6200;
        color: black !important;
        border: none;
        text-decoration: none;
        padding: .5em 1em;
        font-size: 1em;
        border-radius: 25px;
    }
    .dsb-slider .button:hover {
        background-color: #193662;
        color: white !important;
    }
    .dsb-slider .button:focus {
        outline: 2px solid #193662;
        outline-offset: 2px;
    }
    .dsb-slider .dsb-button-control{
        background-color: #FF6200;
        color: #fff !important;
        border: none;
        text-decoration: none;
        padding: .5em;
        position: absolute;
        right: 2em;
        bottom: 2em;
        z-index: 15;
        cursor: pointer;
    }
    .dsb-slider .dsb-button-control:hover {
        background-color: #193662;
        color: white !important;
    }
    .dsb-slider .dsb-button-control:focus {
        outline: 2px solid white;
        outline-offset: 2px;
    }
    .dsb-slider h2.heading:focus {
        outline: 0;
    }
    /* mobile */
    @media (max-width: 767px) {

        .dsb-slider h2.heading {
            font-size: 1em;
            line-height: 1.2em;
            padding-bottom: 5px;
        }
        .dsb-slider .lead {
            font-size: .8em;
            line-height: 1em;
            margin-bottom: 1em;
            max-width: 80%;
        }
        .dsb-slider .slide-caption {
            position: relative;
            width: 100%;
            padding: 1em 1em 2em;
        }
        .dsb-slider .button {
            padding: .3em .5em;
            font-size: .8em;
        }
        .dsb-slider .swiper-pagination {
            left: 0;
            bottom: 0;
            text-align: left;
            margin-left:0;
            padding-left: 1em;
        }
        .dsb-slider .dsb-button-control{
            right: 1em;
            bottom: 1em;
        }
        .dsb-slider .dsb-button-control:focus {
            outline: 2px solid #193662;
            outline-offset: 2px;
        }
    }

    </style>
</head>
<body>

<div id="slider-id" class="swiper dsb-slider">
    <div class="swiper-wrapper">
        <!-- Swiper Slide 1 -->
        <div class="swiper-slide">
            <img src="https://via.placeholder.com/500x300?text=Slide+1" alt="Description for Image 1">
            <div class="carousel-caption">
                <p class="lead">Caption for Image 1</p>
            </div>
            <div class="slide-caption">
                <h2 class="heading" tabindex="0">Heading for Slide 1</h2>
                <p class="lead">Description for Slide 1</p>
                <a class="button" href="#">Button Text</a>
            </div>
        </div>
        <!-- Swiper Slide 2 -->
        <div class="swiper-slide">
            <img src="https://via.placeholder.com/500x300?text=Slide+2" alt="Description for Image 2">
            <div class="carousel-caption">
                <p class="lead">Caption for Image 2</p>
            </div>
            <div class="slide-caption">
                <h2 class="heading" tabindex="0">Heading for Slide 2</h2>
                <p class="lead">Description for Slide 2</p>
                <a class="button" href="#">Button Text</a>
            </div>
        </div>
    </div>
    <div class="swiper-pagination"></div>
    <button class="dsb-button-control" aria-pressed="false">
        <span class="screen-reader-text">Pause</span>
        <span class="dashicons dashicons-controls-pause"></span>
    </button>
</div>

<!-- Include Swiper's JS and jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<script>
    let args = {
        loop: true,
        speed: 1000,
        autoplay: {
            delay: 5000,
        },
        pagination: {
            el: '.swiper-pagination',
            clickable: true,
        },
        on: {
            afterInit: function (dsb_slider) {
            // Jump to the current active bullet on tab
            const button = document.querySelectorAll('#slider-id .button');
            button.forEach(function (item) {
                item.addEventListener('keydown', function (event) {
                    if (event.keyCode === 9) {
                        event.preventDefault();
                        const activeBullet = document.querySelector('.swiper-pagination-bullet-active');
                        activeBullet.focus();
                    }
                });
            });

            // Space key to click pagination bullet and focus on h2 when clicked
            const pagination = document.querySelectorAll('#slider-id .swiper-pagination-bullet');
            pagination.forEach(function (item, index) {
                item.addEventListener('keydown', function (event) {
                    if (event.keyCode === 32) {
                        event.preventDefault();
                        item.click();
                    }
                });
                item.addEventListener('click', function() {
                    const h2Element = dsb_slider.slides[index].querySelector('h2');
                    if (h2Element) {
                        h2Element.focus();
                    }
                });
            });

            // Play/Pause control button
            const controlBtn = document.querySelector('#slider-id .dsb-button-control');
            controlBtn.addEventListener('click', function () {
                if (this.getAttribute('aria-pressed') === 'false') {
                    dsb_slider.autoplay.stop();
                    this.querySelector('.screen-reader-text').textContent = 'Play';
                    this.querySelector('.dashicons').classList.remove('dashicons-controls-pause');
                    this.querySelector('.dashicons').classList.add('dashicons-controls-play');
                    this.setAttribute('aria-pressed', 'true');
                } else {
                    dsb_slider.autoplay.start();
                    this.querySelector('.screen-reader-text').textContent = 'Pause';
                    this.querySelector('.dashicons').classList.remove('dashicons-controls-play');
                    this.querySelector('.dashicons').classList.add('dashicons-controls-pause');
                    this.setAttribute('aria-pressed', 'false');
                }
            });
        },
        }
    };

    (function($){
        var initializeBlock = function() {
            const dsb_slider = new Swiper('#slider-id', args);
        }

        $(document).ready(function(){
            initializeBlock();
        });
    })(jQuery);
</script>

</body>
</html>

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top