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)

Leave a Reply

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