Content
- Required content
- Flow content.
Note that all direct children elements will be turned into slides - any non-slide additions to this wrapper element should be done after the custom element is defined.
Wrap a collecton of elements in this wrapper element and it will automatically provide a functional, accessible carousel.
Conditionally load the JavaScript only if the <pg-carousel> is present on the page at load:
if (document.querySelectorAll('pg-carousel').length) import('./carousel.min.js');
Load the script as a module in WordPress:
wp_enqueue_script_module( 'pg-carousel', get_theme_file_uri( 'js/pg-carousel.min.js' ), [], filemtime( get_theme_file_path( 'js/pg-carousel.min.js' ) ) );
| Name | Description | Default |
|---|---|---|
aria-labelledby |
Required. ID reference for an element containing the accessible name for region containing the carousel (e.g. a heading element). | undefined |
data-autocarousel |
ID reference for a <template> element containing the markup for the play/pause button. See below. |
undefined |
data-autoplay |
When present, configures the carousel to auto-advance. | undefined |
data-controlslabel |
Label for the controls wrapper element (for translation purposes). | Slider controls |
data-markerlabel |
Each marker/indicator receives an accessible name indicating its one-based index in the carousel. This string, which should contain {current} and {total} literally, is used for translation purposes. |
Show slide {current} of {total} |
data-markers |
When present, outputs markers/indicators to show how many slides are present and which is active. Optionally, when set to buttons, outputs interactive markers/indicators. |
undefined |
data-nextbtn |
ID reference for a <template> element containing the markup for the next button. See below. |
undefined |
data-prevbtn |
ID reference for a <template> element containing the markup for the previous button. See below. |
undefined |
data-slidelabel |
Each slide receives an accessible name indicating its one-based index in the carousel. This string, which should contain {current} and {total} literally, is used for translation purposes. |
{current} of {total} |
data-start |
Label for the play/pause button for auto-advancing carousels when the advancement is paused (for translation purposes). | Start slide rotation |
data-stop |
Label for the play/pause button for auto-advancing carousels when the advancement is playing (for translation purposes). | Stop slide rotation |
| Name | Description |
|---|---|
slideCount |
Total number of slides. |
activeSlide |
1-based index of currently active slide. |
| Name | Description |
|---|---|
pg-carousel-change |
Fires whenever the active slide is updated. |
If defined, the component can make use of a templated <button> to override the included, barebones previous button. The defined template should be a <button> element with a class of prevbtn.
Be sure to give this button an accessible name.
<template id="prevbtn"> <button type="button" class="prevbtn"> <svg width="44" height="44" aria-hidden="true"> <path fill="none" stroke="currentcolor" d="m21.22 29-7.021-7 7.021-7M14 22h16"/> </svg> <span class="screen-reader-text">Previous slide</span> </button> </template>
If defined, the component can make use of a templated <button> to override the included, barebones next button. The defined template should be a <button> element with a class of nextbtn.
Be sure to give this button an accessible name.
<template id="nextbtn"> <button type="button" class="nextbtn"> <svg width="44" height="44" aria-hidden="true"> <path fill="none" stroke="currentcolor" d="m22.78 15 7.021 7-7.021 7M30 22H14"/> </svg> <span class="screen-reader-text">Next slide</span> </button> </template>
If defined, the component can make use of a templated <button> to override the included, barebones play/pause button. The defined template should be a <button> element with a class of playbtn.
For styling purposes, descendents of the <button> that should only be displayed when the video is paused should be given a class of play and those that should only be displayed when the video is playing should be given a class of pause.
<template id="autocarousel"> <button type="button" class="playbtn"> <svg width="30" height="30" aria-hidden="true"> <circle cx="15" cy="15" r="15"/> <path class="play" fill="#fff" d="m20 15-7.5 4.33v-8.66z"/> <path class="pause" fill="#fff" d="M17.75 19h-1v-8h1zm-4.5-8h-1v8h1z"/> </svg> </button> </template>
No additional CSS is required beyond that called for by the overall page design. That said, it is often likely that the non-active slides should be somehow hidden (or less prominent). These inactive slides can be wholesale targeted based on the presense of the aria-hidden="true" attribute.
Utilizes default, unstyled previous/next buttons.
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Utilizes default, unstyled previous/next buttons.
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined .slide-wrap [role="group"] {display: grid; place-items: center;}
pg-carousel:defined .slide-wrap [role="group"] > * {grid-area: 1 / 1; font-size: 5rem;}
Utilizes the previous/next buttons defined within a <template> element whose [id] is passed via the [data-prevbtn] and [data-nextbtn] attributes on the component.
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Utilizes a translated string for the controls wrapper element, defined by the data-controlslabel attribute on the component. (Note that this string is used within the controls wrapper element's aria-label attribute.)
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Utilizes a translated string for each slide element, defined by the data-slidelabel attribute on the component. (Note that this string is used within each slide element's aria-label attribute.)
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Non-interactive indicators can be added with the [data-markers] attribute.
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined .pg-carousel-markers {display: flex; gap: .5rem; padding-left: 0;}
pg-carousel:defined .pg-carousel-markers li {width: 1rem; height: 1rem; border: 1px solid; border-radius: 50%; list-style: none;}
pg-carousel:defined .pg-carousel-markers [aria-disabled="true"] {background-color: red;}
Utilizes a translated string for each marker/indicator element, defined by the data-markerlabel attribute on the component. (Note that this string is used within each marker/indicator element's aria-label attribute.)
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined .pg-carousel-markers {display: flex; gap: .5rem; padding-left: 0;}
pg-carousel:defined .pg-carousel-markers li {width: 1rem; height: 1rem; border: 1px solid; border-radius: 50%; list-style: none;}
pg-carousel:defined .pg-carousel-markers [aria-disabled="true"] {background-color: red;}
Interactive indicators can be added with the [data-markers="buttons"] attribute.
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined .pg-carousel-markers {display: flex; gap: .5rem; padding-left: 0;}
pg-carousel:defined .pg-carousel-markers li {width: 1rem; height: 1rem; border: 1px solid; border-radius: 50%; list-style: none;}
pg-carousel:defined .pg-carousel-markers [aria-disabled="true"] {background-color: red;}
Utilizes a translated string for each marker/indicator element, defined by the data-markerlabel attribute on the component. (Note that this string is used within each marker/indicator element's aria-label attribute.)
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined .pg-carousel-markers {display: flex; gap: .5rem; padding-left: 0;}
pg-carousel:defined .pg-carousel-markers li {width: 1rem; height: 1rem; border: 1px solid; border-radius: 50%; list-style: none;}
pg-carousel:defined .pg-carousel-markers [aria-disabled="true"] {background-color: red;}
Add auto-advancing functionality to the carousel by adding the [data-autoplay] attribute. The auto-play functionality will stop automatically if the user hovers over the slides or focuses within the component.
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Utilizes the play/pause button defined within a <template> element whose [id] is passed via the [data-autoplay] attribute on the component.
The following sample styles are applied to the component above. (You will need to provide your own reset for the <button> elements themselves.)
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
pg-carousel:defined :is(.playbtn[aria-label="Start slide rotation"] .pause, .playbtn[aria-label="Stop slide rotation"] .play) {display: none;}
Utilizes translated strings for "Start slide rotation" and "Stop slide rotation", defined by the data-start and data-stop attributes on the component, respectively. (Note that these strings are used within the play/pause button's aria-label attribute.)
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
Utilizing the activeSlide & slideCount properties alongside the pg-carousel-change event, a numeric status can be added.
The following sample styles are applied to the component above.
pg-carousel:defined .slide-wrap {display: grid;}
pg-carousel:defined .slide-wrap * {grid-area: 1 / 1;}
pg-carousel:defined .slide-wrap [aria-hidden="false"] {z-index: 1;}
The following additional sample scripts are applied to the component above.
customElements.whenDefined('pg-carousel').then(() => {
const theCarousel = [some reference to this carousel component];
const div = document.createElement('div');
div.classList.add('status');
div.textContent = `${theCarousel.activeSlide} of ${theCarousel.slideCount}`;
theCarousel.appendChild(div);
theCarousel.addEventListener('pg-carousel-change', () => {
theCarousel.querySelector('.status').textContent = `${theCarousel.activeSlide} of ${theCarousel.slideCount}`;
});
});
The required child elements are not present.
Result: a console error is thrown.
The required [aria-labelledby] attribute is not set to define an accessible name for the component.
Result: a console error is thrown.
The referenced previous button template does not contain a <button> element with a class of prevbtn.
Note that the component has a aria-labelledby attribute set to the id attribute of the above <h2> and <summary> elements.
Result: silently falls back to the default previous button template.
The referenced next button template does not contain a <button> element with a class of nextbtn.
Note that the component has a aria-labelledby attribute set to the id attribute of the above <h2> and <summary> elements.
Result: silently falls back to the default next button template.
The referenced play/pause button template does not contain a <button> element with a class of playbtn.
Note that the component has a aria-labelledby attribute set to the id attribute of the above <h2> and <summary> elements.
Result: silently falls back to the default play/pause button template.