Play/Pause button for cover video background
Published: – Leave a comment
Having a video in your cover block as background may hurt accessibility, because you cannot control its state. It usually automatically plays and cannot be stopped. However, the cover block doesn’t have such controls out of the box.
Accessibility background
As the WCAG Success Criterion 2.2.2 states:
For any moving, blinking or scrolling information that (1) starts automatically, (2) lasts more than five seconds, and (3) is presented in parallel with other content, there is a mechanism for the user to pause, stop, or hide it unless the movement, blinking, or scrolling is part of an activity where it is essential; […]
In order to achieve such a solution, a play/pause button is a so-called “toggle” button. That means, it’s a button that activates or deactivates one particular action upon click. If the action is activated, the second time you click on the button, the action gets deactivated.
This toggle button not only should pause/play the video, but also changing the state of the button. A toggle button is using the attribute aria-pressed
to determine whether its current state is “active” or “inactive”.
A solution
Philip Roth came up with an idea to solve this with such a toggle button and a little bit of JavaScript:
https://social.tchncs.de/@phillip/113317784082959086?kjy=spring
And since I like his solution, I’ll cover a complete guide on how to achieve such a result in WordPress (which is also a little different when it comes to the code).
JavaScript
The heart of the solution is a JavaScript code that pauses and plays the video on the one hand and sets the correct state of the button on the other. Additionally, I also toggle a class for is-playing
and is-paused
to the button, which I then use to check for the current state. I could also just check the aria-pressed
property, though.
In the end, the code looks like this:
document.addEventListener( 'DOMContentLoaded', () => {
const pauseButtons = document.querySelectorAll( '.my-video__button' );
const togglePlayback = ( event ) => {
const button = event.currentTarget;
const screenReaderText = button.querySelector( '.screen-reader-text' );
const video = button.closest( '.wp-block-cover' ).querySelector( '.wp-block-cover__video-background' );
if ( button.classList.contains( 'is-playing' ) ) {
video.pause();
button.ariaPressed = true;
button.classList.add( 'is-paused' );
button.classList.remove( 'is-playing' );
button.querySelector( 'use' ).setAttribute( 'href', '#play' );
screenReaderText.textContent = myVideoPause.play;
}
else {
video.play();
button.ariaPressed = false;
button.classList.add( 'is-playing' );
button.classList.remove( 'is-paused' );
button.querySelector( 'use' ).setAttribute( 'href', '#pause' );
screenReaderText.textContent = myVideoPause.pause;
}
}
for ( const pauseButton of pauseButtons ) {
pauseButton.addEventListener( 'click', togglePlayback );
}
} );
Code language: JavaScript (javascript)
As you may already see here, I also change the attribute of a use
-element, which I use to change the button’s content from a pause icon to a play icon. Additionally, I have a span
with screen reader text, which is changed to a property of the object myVideoPause
, which is a localized string registered via wp_localize_script
.
Register script
I saved the script above in my theme under /assets/js/video-pause.js
and also created a minified version of it in /assets/js/video-pause.min.js
. Then, I use this function to register and localize it:
/**
* Register assets.
*/
static function my_register_assets(): void {
$is_debug = \defined( 'WP_DEBUG' ) && \WP_DEBUG || \defined( 'SCRIPT_DEBUG' ) && \SCRIPT_DEBUG;
$suffix = $is_debug ? '' : '.min';
$path = \get_template_directory() . '/assets/js/video-pause' . $suffix . '.js';
$url = \get_template_directory_uri() . '/assets/js/video-pause' . $suffix . '.js';
\wp_register_script( 'my-video-pause', $url, [], (string) \filemtime( $path ), true );
\wp_localize_script(
'my-video-pause',
'myVideoPause',
[
'pause' => \esc_js( \__( 'Pause video', 'textdomain' ) ),
'play' => \esc_js( \__( 'Play video', 'textdomain' ) ),
]
);
}
\add_action( 'wp_enqueue_scripts', 'my_register_assets' );
Code language: PHP (php)
Now you also know what myVideoPause.pause
and myVideoPause.play
is (either “Pause video” or “Play video”).
The actual enqueueing of the script does then take place inside the block markup, since it should only be enqueued if a cover block has a video background.
Block markup
Enqueuing the script and adding the actual button element can be done using the render_block_core/cover
filter. Here, it’s also checked whether the current cover block even has a video background.
/**
* Set a pause button if the cover has a video background.
*
* @param string $block_content Block content
* @param mixed[] $block Block data
* @return string Updated block content
*/
static function my_set_pause_button( string $block_content, array $block ): string {
if ( empty( $block['attrs']['backgroundType'] ) || $block['attrs']['backgroundType'] !== 'video' ) {
return $block_content;
}
\wp_enqueue_script( 'my-video-pause' );
$markup = '<div class="my-video__pause-play">
<button class="my-video__button my-video__button--pause-play is-playing" type="button" aria-pressed="false">
<svg class="my-video__button--icon" aria-hidden="true"><use href="#pause"></use></svg>
<span class="screen-reader-text">' . \esc_html__( 'Pause video', 'textdomain' ) . '</span>
</button>
</div>';
return \str_replace( '</video>', '</video>' . $markup, $block_content );
}
\add_filter( 'render_block_core/cover', 'my_set_pause_button' );
Code language: PHP (php)
Et voilà, you’ll end up with an actual button to play/pause button, which improves accessibility for your WordPress site.
Please also keep in mind that you need to adjust the button with CSS to make it clickable. You can use the following CSS and adapt it to your needs:
.wp-block-cover {
position: relative;
}
.my-video__button {
background-color: rgba(255, 255, 255, .75);
inset-block-end: 0;
inset-inline-end: 0;
line-height: 1;
padding: 6px;
position: absolute;
width: auto;
z-index: 10;
}
.my-video__button:focus,
.my-video__button:hover {
background-color: #fff;
}
.my-video__button--icon {
height: 24px;
width: 24px;
}
Code language: CSS (css)