DEV3 Technologies home

Sticky mini audio player dock

A fixed bottom audio dock that plays any link marked with data-audio and keeps playing while the visitor browses the page.

WordPressUtilitiesaudioplayerpodcastaccessibility

Live preview

Code

<?php
/**
 * Sticky audio dock.
 *
 * @package Acme_Theme
 */

defined( 'ABSPATH' ) || exit;

function acme_audio_dock_assets(): void {
	$uri = get_template_directory_uri() . '/assets/';
	wp_enqueue_style( 'acme-dock', $uri . 'audio-dock.css', array(), '1.0.0' );
	wp_enqueue_script( 'acme-dock', $uri . 'audio-dock.js', array(), '1.0.0', array( 'in_footer' => true, 'strategy' => 'defer' ) );
}
add_action( 'wp_enqueue_scripts', 'acme_audio_dock_assets' );

function acme_audio_dock_markup(): void {
	?>
	<div class="acme-dock" role="region" aria-label="<?php esc_attr_e( 'Audio player', 'acme-theme' ); ?>" hidden>
		<button type="button" class="acme-dock__play" aria-label="<?php esc_attr_e( 'Play or pause', 'acme-theme' ); ?>"></button>
		<span class="acme-dock__title"></span>
		<input type="range" class="acme-dock__seek" min="0" max="100" value="0" aria-label="<?php esc_attr_e( 'Seek', 'acme-theme' ); ?>">
		<audio preload="none"></audio>
	</div>
	<?php
}
add_action( 'wp_footer', 'acme_audio_dock_markup' );

// Helper for templates: a link the dock script picks up.
function acme_audio_link( string $url, string $title ): string {
	return sprintf( '<a href="%1$s" data-audio="%1$s" data-title="%2$s">%3$s</a>', esc_url( $url ), esc_attr( $title ), esc_html( $title ) );
}

How it works

What it solves

Listening to an episode should not stop when the visitor clicks around. A small docked player gives one persistent control strip, so any episode link on the page can play without a new tab or a heavyweight plugin.

How it works

Links carrying data-audio are intercepted through a single delegated click listener, so lists loaded later work too. The script loads the URL into one audio element inside a fixed footer region, shows the dock, and mirrors state onto a play button and a range slider that doubles as the seek bar. The markup is printed in wp_footer, and acme_audio_link() outputs links with escaped attributes.

Without JavaScript, the link is still a normal download link.

Adapting it

Add playback speed by setting audio.playbackRate from a select, and remember the last position per URL with a try/catch around localStorage. For full page navigation continuity, pair it with a fragment-swapping router; on a classic multi-page site playback pauses at each load. Style the dock to match the theme.

Pitfalls

  • Browsers block autoplay unless it follows a user gesture; the click handler satisfies that.
  • Keep preload="none" to avoid downloading files nobody plays.
  • Give the slider a text alternative; time values read better with aria-valuetext.
  • Remember the dock covers the bottom of the page; add matching bottom padding.

How to use it

Add the three files and require the PHP from functions.php.

Output episode links with echo acme_audio_link( $mp3_url, get_the_title() );.

Add padding-bottom: 4rem to body while the dock is visible.

Licence: GPL-2.0-or-later. This snippet comes from WordPress code and is GPL-2.0-or-later.

Related snippets