Okay, this is more of an experiment I was running because I was reached out by a friend about a theme question.

This actually got me thinking about the shortcodes. The audio and video ones in particular. The reason is that when you use the [audio] shortcode WordPress will use MediaElementJS and enqueue both the JavaScript file and the CSS stylesheet.

Turns our there is a filter for those! Well, two really. One for each one. I wanted to dig deep for this one because styling the player is something I have wanted to do for a long time. Today I found out I can!

Yes, I am excited about it.

Yes, I am writing about it.

Yes, I will share what I found with you.

The steps

This took me about a day’s worth of effort only because I didn’t really know what I was looking for. I knew I needed to figure out what styles were being used and where. By default WordPress registers a few scripts and styles for MediaElements. The styles are registered in the script-loader file. There are two that are registered. The second one –wp-mediaelement– depends on the first registered one so really it is loading two files when either shortcode is used.

Now, how did I find this out?

I looked up wp-mediaelement in the project and found 16 results. The first place I looked was the ajax-actions file only because it was the first result and I wanted to see how it was done as well. Looked at the file and noticed that it uses wpview_media_sandbox_styles() to get the stylesheet URLs but not exactly what I was looking for. Though it is a neat little function.

Next up was the media.php file. This was the one I really should have been looking in. 6 results and one was from the wpview_media_sandbox_styles function so I was making some progress I guess. In the first result it was inside of the wp_playlist_scripts() function and it enqueues the style and a playlist script. Not exactly what I need but getting close.

The second result landed me where I needed to be. A nice filter. The wp_audio_shortcode_library to be precise. What’s really nice is the video is much like it as well. It is wp_video_shortcode_library and they work the same way.

The Filters

apply_filters( 'wp_audio_shortcode_library', 'mediaelement' );
apply_filters( 'wp_video_shortcode_library', 'mediaelement' );

Pretty cool, right? So then how would it be used?

In the functions.php of your theme you could potentially do something like:

add_filter( 'wp_audio_shortcode_library', 'jmc_new_lib' );
add_filter( 'wp_video_shortcode_library', 'jmc_new_lib' );
function jmc_new_lib(){
	// Because we still want the script to load but not the styles
	wp_enqueue_script( 'wp-mediaelement' );
	wp_script_add_data( 'wp-mediaelement', 'conditional', 'lt IE 9' );

	// Enqueue our own styles here.
	wp_enqueue_style( 'jmc-media-styles', get_template_directory_uri() . '/css/media.css' );

	return '';

Super sweet if you ask me. That’s great and all but what about the markup? Now we have to think about what needs to be styled right?

Well, I’ve gone ahead and extracted some of the classes for both the audio and video markup to make it easier:

.mejs-offscreen {}
.mejs-container {}
.svg {}
.wp-audio-shortcode {}
.mejs-audio {}
.mejs-inner {}
.mejs-mediaelement {}
.mejs-layers {}
.mejs-poster {}
.mejs-layer {}
.mejs-controls {}
.mejs-button {}
.mejs-playpause-button {}
.mejs-play {}
.mejs-time {}
.mejs-currenttime-container {}
.mejs-currenttime {}
.mejs-time-rail {}
.mejs-time-total {}
.mejs-time-slider {}
.mejs-time-buffering {}
.mejs-time-loaded {}
.mejs-time-current {}
.mejs-time-handle {}
.mejs-time-float {}
.mejs-time-float-current {}
.mejs-time-float-corner {}
.mejs-duration-container {}
.mejs-duration {}
.mejs-volume-button {}
.mejs-mute {}
.mejs-horizontal-volume-slider {}
.mejs-horizontal-volume-total {}
.mejs-horizontal-volume-current {}
.mejs-horizontal-volume-handle {}
.mejs-clear {}
.wp-video {}
.wp-video-shortcode {}
.mejs-video {}
.mejs-overlay {}
.mejs-overlay-loading {}
.mejs-overlay-error {}
.mejs-overlay-play {}
.mejs-overlay-button {}
.mejs-volume-slider {}
.mejs-volume-total {}
.mejs-volume-current {}
.mejs-volume-handle {}
.mejs-fullscreen-button {}

Those are some of the common classes that are used in the final markup. It may not be a complete list but it is a starting point for many and I hope it does help somebody out in theming the audio and video post formats. I will mention this because I know it may be asked down the road: some of those classes may have inline styles so it would be w

I also created a quick gist for the files if you only wanted to target one media type. This is useful if the user has a playlist.

In the following example, I’ve removed the core action and am only documenting the basics.

// remove the scripts/styles originally enqueued
remove_action( 'wp_playlist_scripts', 'wp_playlist_scripts' );

// enqueue ours instead
add_action( 'wp_playlist_scripts', 'jmc_new_liststyles', 10, 2 );
function jmc_new_liststyles( $type, $style ) {
	// $type is the type of playlist either an 'audio' or 'video'.
	// $style can be core 'light' or 'dark' but can add more by having user input
	// and enqueueing the needed style.
	wp_enqueue_style( 'jmc-style', 'path/to/file' );

	// Because we still want to enqueue the script just not the style.
	wp_enqueue_script( 'wp-playlist' );

What’s cool about that is that you really can add your own styles if you want. I know there are some themes that take advantage of “skins” or color schemes and could really benefit from this. I may just try and do this on one of my days off or when I can. In the meantime I hope this helps some plugin authors and even more theme authors with styling and using core methods rather than relying on using wp_deregister_style() for this.