Content Slider
A content slider shows a group of items or content, called slides, by displaying one or more slides at a time one after the other. Users can move between slides by using slider controls.
NOTE:
- New to accessibility or uncertain of requirements, it will be helpful to review all sections below.
- Already familiar with requirements, skip to the “Working Example” section for sample HTML, CSS and JavaScript (when needed), along with a working demo.
- The textual based content in the content slider MUST be at least 4.5:1 against the background color if it’s a standard text in default, focused and hover state.
- The minimum contrast requirement ratio of 3:1 for the large text or text with 14pts and bold MUST be met in default, focused and hover state.
- The contrast requirement of 3:1 ratio MUST be met with the adjacent colors for the custom focus indicator if used for the interactive elements.
- The contrast ratio requirement of 3:1 MUST be met with the adjacent colors for the user interface control in default, focused and hover state.
-
Only color MUST not be used to distinguish the current state of the slider picker
control.
- There SHOULD be a visual cue like underline, different formatting, different shape or so on that be used to help distinguish the current state of the slider picker control.
-
IF the slides rotate automatically, provide a native HTML button to start and stop
the autorotation as needed.
- Best practice is NOT to start autorotation on page load.
- The content slider rotation is paused on hovering the mouse over any content slider content.
- The rotation resumes when the mouse is moved away from the content slider.
- All content slider functionalities MUST be operable with a keyboard with and without a screen reader turned on
-
Changes in the content slider region SHOULD be conveyed using an
aria-live="polite"
attribute on the parent container consisting of all the slides.-
Alternatively,
role="status"
CAN be specified as well on the parent container that consists of all the slides.
-
Alternatively,
- When the previous slide or next slide button is activated, the focus MUST remain on the button itself.
- The non-visible slides MUST be hidden using native HTML hidden attribute or CSS
display:none
property.-
Additionally,
aria-hidden="true"
andtabindex="-1"
CAN be used.
-
Additionally,
- A clear indication of visual focus MUST be provided for all the content slider controls.
-
The container of the content slider SHOULD be defined using native HTML
<section>
element (alternativelyrole="region"
can be specified).-
The
aria-label
attribute SHOULD be used to define an accessible name for the region.
-
The
-
On each slide container,
role="group"
SHOULD be added.-
The
aria-label
with value “Slide N of N” SHOULD be given to state the count of total slides in the content slider.
-
The
- If there are images defined within the content slider – ensure that all the accessibility requirements are adhered to. For more information, refer to the Images tutorial .
-
The content of the slides SHOULD be structured using standard HTML mark-up.
For example:- The headings can be structured using HTML heading mark-up
<h2> - <h6>
. -
The lists can be structured using HTML list mark-up
<ul>
,<ol>
,<li>
and so on as per the type of relation.
- The headings can be structured using HTML heading mark-up
- Below is recommended for mobile platforms.
- The interactive elements SHOULD have enough spacing such that the target area doesn’t overlap with any other target area.
-
A target offset of at least 24 CSS pixels SHOULD be provided to every adjacent
target area of the interactive elements.
For content sliders that has grouped buttons as slide picker controls
-
Each picker control SHOULD be defined with native HTML
<button>
element and labelled usingaria-label
attribute.- If an image is used to identify the slider picker controls, then a textual description MUST be defined for the image control.
-
If the image is defined using
<img>
element, use analt
attribute with descriptive value. -
If the image is defined using
<svg>
element, userole="img"
andaria-label
attribute to provide a role and an accessible name for the element.
Note: Providing ARIA based role and attribute on SVG image ensures robust support across different environments.
- The slide picker control SHOULD have a clear visible focus and keyboard support SHOULD be present.
-
The set of slide picker controls SHOULD be contained in an element with
role="group"
. -
The group containing the picker controls SHOULD have an accessible label provided by
the value of
aria-label
that will identify the purpose of the controls. - On activating any of the slide picker controls, the respective slide MUST be displayed.
For example,
<!-- Content Slider parent container -->
<div role="region" aria-label="Featured Articles Carousel">
<button aria-label="Previous Slide">...</button>
<!-- Parent container of all the slides -->
<div aria-live="polite">
<!-- Slide containers -->
<div aria-hidden="false" role="group" aria-label="slide 1 of 4">
<h2>MyLab</h2>
<img src="./content-slider-1.jpg" alt="" loading="lazy" width="358" height="179">
<p>Data-driven guidance to help improve results with engaging, interactive content by expert authors.
<a href="#">Explore MyLab<sup>®</sup></a>
</p>
</div>
<div aria-hidden="true" role="group" aria-label="slide 2 of 4">
...
...
</div>
...
</div>
<button aria-label="Next Slide">...</button>
<!-- Slider picker controls -->
<div role="group">
<button class="active" aria-current="true"><span class="hidden">Slide 1 - MyLab</span></button>
<button><span class="hidden">Slide 2 - Mastering</span></button>
...
</div>
</div>
A well-defined content slider benefits majorly the below users.
- People with cognitive disabilities
- People using speech input
- People with limited dexterity
- People using keyboard only
- People with visual disabilities
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/>
<h1>Content Slider</h1>
<div class="carousel" role="region" aria-label="Featured Articles Carousel">
<button class="previous fas fa-chevron-left" aria-label="Previous Slide"></button>
<div class="slides" aria-live="polite">
<div class="slide" aria-hidden="false" role="group" aria-label="slide 1 of 4">
<div class="card reorder">
<h2>MyLab</h2>
<img src="content-slider-1.jpg" alt="Women working on a laptop at a table" loading="lazy" width="358" height="179">
<p>
Data-driven guidance to help improve results with engaging, interactive content by expert authors.
<a href="#">Explore MyLab</a>
</p>
</div>
</div>
<div class="slide" aria-hidden="true" role="group" aria-label="slide 2 of 4">
<div class="card reorder">
<h2>Mastering</h2>
<img src="content-slider-2.jpg" alt="Women working on a laptop on the couch" loading="lazy" width="358" height="179">
<p>
Tools to help create immersive science & engineering courses that increase engagement.
<a href="#" tabindex="-1">Explore Mastering</a>
</p>
</div>
</div>
<div class="slide" aria-hidden="true" role="group" aria-label="slide 3 of 4">
<div class="card reorder">
<h2>Revel</h2>
<img src="content-slider-3.jpg" alt="Man looking at a cell phone while on mass transit" loading="lazy" width="358" height="179">
<p>
A dynamic mobile reading experience that blends digital text and media to bring concepts to life.
<a href="#" tabindex="-1">Explore Revel</a>
</p>
</div>
</div>
<div class="slide" aria-hidden="true" role="group" aria-label="slide 4 of 4">
<div class="card reorder">
<h2>eTextbooks and Pearson+</h2>
<img src="content-slider-4.jpg" alt="Woman looking at a cell phone" loading="lazy" width="358" height="179">
<p>
The engaging content digital natives need, in the format they prefer, at a price point they expect.
<a href="#" tabindex="-1">Explore eTextbooks</a>
</p>
</div>
</div>
</div>
<button class="next fas fa-chevron-right" aria-label="Next Slide"></button>
<div class="navigation" role="group">
<button class="active" aria-current="true"><span class="hidden">Slide 1 - MyLab</span></button>
<button><span class="hidden">Slide 2 - Mastering</span></button>
<button><span class="hidden">Slide 3 - Revel</span></button>
<button><span class="hidden">Slide 4 - eTextbooks and Pearson+</span></button>
</div>
</div>
:root {
/* The height will be adjusted based on your content */
--carousel-height: 76%;
--slide-width: calc(100% / 1);
}
* {
box-sizing: border-box;
}
body {
background-color: #f5f5f5;
padding: 20px;
font-family: 'Open Sans",', sans-serif;
}
.carousel {
position: relative;
width: calc(100% - 40px);
max-width: 500px;
height: var(--carousel-height);
margin: 0 auto;
padding: 0 20px;
}
.previous,
.next {
display: flex;
justify-content: center;
align-items: center;
padding: 5px 10px;
position: absolute;
top: calc(50% - 16px);
cursor: pointer;
font-size: 32px;
border: 0;
background: none;
}
.previous { left: -30px; }
.next { right: -30px; }
.slides {
list-style: none;
padding: 0;
margin: 0;
display: flex;
width: 100%;
overflow: hidden;
}
.slide {
flex: 0 0 calc(100% / 1 - 10px);
margin: 0 5px;
padding: 20px;
height: var(--carousel-height);
display: flex;
align-items: center;
font-size: 16px;
line-height: 20px;
background-color: white;
}
@media screen and (max-width: 768px) {
.slide {
font-size: 14px;
line-height: 18px;
align-items: flex-start;
}
}
@media only screen and (max-width: 480px) {
:root {
--carousel-height: 50%;
--slide-width: 100%;
}
.carousel {
width: 100%;
padding: 0;
}
.previous, .next {
top: calc(50% - 12px);
font-size: 24px;
}
.previous { left: 0; }
.next { right: 0; }
.slides { margin: 0; }
.slide { width: 100%; }
.card { height: 100%; }
img {
max-width: 100%;
height: auto;
}
}
.slide a {
color: #007a9c;
font-weight: bold;
text-decoration: none;
margin-top: 1.5rem;
}
.navigation {
position: absolute;
left: 0;
bottom: -40px;
list-style: none;
padding: 0;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.navigation button {
display: inline-block;
width: 17px;
height: 17px;
margin: 0 5px;
border-radius: 50%;
background-color: white;
border: 3px solid #000;
cursor: pointer;
}
.navigation button.active {
opacity: 1;
width: 23px;
height: 23px;
background-color: #000;
}
.navigation button:focus{
outline: .15em solid #000;
outline-offset: 1px;
}
h2 {
font-size: 1.4rem;
margin-top: .5em;
margin-bottom: .2em;
line-height: 1;
}
.cards {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0;
}
.cards > * { flex: 0 1 25em; }
.card {
margin: .75em;
padding: .75em;
border-radius: 3px;
border: 2px #ccc solid;
border-radius: .6em;
background-color: white;
position: relative;
}
img {
width: 100%;
height: auto;
}
.reorder {
display: flex;
flex-direction: column;
}
.reorder img {
max-width: 100%;
order: -1;
}
.card > * a, .card > .cta { display: block; }
.card h2 > a {
text-decoration: none;
color: inherit;
}
.linkify:hover {
cursor: pointer;
box-shadow: 0 0 0 3px rgba(38, 50, 190, .8);
}
.cards .isfocused {
outline: 0;
box-shadow: 0 0 0 3px rgba(38, 50, 190, .8);
}
.isfocused a:focus { outline: none; }
.card .cta {
text-decoration: underline;
color: #242AC1;
font-weight: bold;
}
.hidden{
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
h1 { text-align: left; }
sup {
top: -.6em;
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
let previousButton, nextButton;
let slidesContainer, slides, slideDots;
let leftMostSlideIndex = 0;
let slideGap = 5;
window.addEventListener('DOMContentLoaded', function(e) {
previousButton = document.querySelector('.previous');
nextButton = document.querySelector('.next');
slidesContainer = document.querySelector('.slides');
slides = slidesContainer.querySelectorAll('.slide');
slideDots = document.querySelectorAll('.navigation button');
cardlink = document.querySelectorAll('.card a');
previousButton.addEventListener('click', previousSlide);
nextButton.addEventListener('click', nextSlide);
slideDots.forEach(function(dot) {
dot.addEventListener('click', function(e) {
goToSlide(Array.prototype.slice.call(slideDots).indexOf(e.target));
});
});
});
function previousSlide() {
if (leftMostSlideIndex > 0) {
goToSlide(leftMostSlideIndex - 1);
} else {
goToSlide(slides.length - 1);
console.log(slides[leftMostSlideIndex])
}
}
function nextSlide() {
if (leftMostSlideIndex < slides.length - 1) {
goToSlide(leftMostSlideIndex + 1);
} else {
goToSlide(0);
}
}
function goToSlide(nextLeftMostSlideIndex) {
const slideWidth = slidesContainer.offsetWidth / 1;
const newScrollLeft = slideWidth * nextLeftMostSlideIndex;
slidesContainer.scrollTo({
left: newScrollLeft,
behavior: 'smooth'
});
slideDots.forEach(function(dot, index) {
if (index === nextLeftMostSlideIndex) {
dot.classList.add('active');
dot.setAttribute('aria-current', 'true');
} else {
dot.classList.remove('active');
dot.setAttribute('aria-current', 'false');
}
});
for (let i = 0; i < slides.length; i++) {
if (i === nextLeftMostSlideIndex) {
slides[i].setAttribute('aria-hidden', false);
cardlink[i].removeAttribute('tabindex');
} else {
slides[i].setAttribute('aria-hidden', true);
cardlink[i].setAttribute('tabindex','-1')
}
}
leftMostSlideIndex = nextLeftMostSlideIndex;
}
Content Slider
MyLab
Data-driven guidance to help improve results with engaging, interactive content by expert authors. Explore MyLab
Mastering
Tools to help create immersive science & engineering courses that increase engagement. Explore Mastering
Revel
A dynamic mobile reading experience that blends digital text and media to bring concepts to life. Explore Revel
eTextbooks and Pearson+
The engaging content digital natives need, in the format they prefer, at a price point they expect. Explore eTextbooks