Improving the WordPress caption shortcode for HTML5

Improving the WordPress caption shortcode for HTML5

The WordPress caption shortcode is probably one of the most used shortcodes. Every time a user adds a caption to an image through the “Add Media” button above the editor it gets inserted in the editor.

But the resulting HTML isn’t that sexy; here’s how I’d improve it.

The original caption shortcode

The default output of the shortcode is functional, but isn’t exactly exciting stuff:

<div id="attachment_283" class="wp-caption aligncenter" style="width: 160px">
	<img src="http://example.com/wp-content/uploads/2013/01/otomie.jpg" alt="Otomie, princess of the otomie" width="150" height="150" class="size-thumbnail wp-image-283">
	<p class="wp-caption-text">Otomie, pricess of the Otomie, together with Thomas Wingfield.</p>
</div>

A lame div and a p… with an in-line style. Meh.

The semantically improved caption shortcode

One problem is that there’s no semantic connection between the image and the caption. So we can add:

By modifying these elements & adding these attributes, we’d have a rock-solid semantic connection between the image and the caption.

/**
 * Improves the caption shortcode with HTML5 figure & figcaption; microdata & wai-aria attributes
 * 
 * @param  string $val     Empty
 * @param  array  $attr    Shortcode attributes
 * @param  string $content Shortcode content
 * @return string          Shortcode output
 */
function jk_img_caption_shortcode_filter($val, $attr, $content = null)
{
	extract(shortcode_atts(array(
		'id'      => '',
		'align'   => 'aligncenter',
		'width'   => '',
		'caption' => ''
	), $attr));
	
	// No caption, no dice... But why width? 
	if ( 1 > (int) $width || empty($caption) )
		return $val;
 
	if ( $id )
		$id = esc_attr( $id );
     
	// Add itemprop="contentURL" to image - Ugly hack
	$content = str_replace('<img', '<img itemprop="contentURL"', $content);

	return '<figure id="' . $id . '" aria-describedby="figcaption_' . $id . '" class="wp-caption ' . esc_attr($align) . '" itemscope itemtype="http://schema.org/ImageObject" style="width: ' . (0 + (int) $width) . 'px">' . do_shortcode( $content ) . '<figcaption id="figcaption_'. $id . '" class="wp-caption-text" itemprop="description">' . $caption . '</figcaption></figure>';
}
add_filter( 'img_caption_shortcode', 'jk_img_caption_shortcode_filter', 10, 3 );

Plunk this in a plugin or a theme’s function.php, and we’re good to go.

Here’s the resulting HTML:

<figure id="attachment_283" aria-describedby="figcaption_attachment_283" class="wp-caption aligncenter" itemscope itemtype="http://schema.org/ImageObject" style="width: 160px">
	<img itemprop="contentURL" src="http://example.com/wp-content/uploads/2013/01/otomie.jpg" alt="Otomie, princess of the otomie" width="150" height="150" class="size-thumbnail wp-image-283">
	<figcaption id="figcaption_attachment_283" class="wp-caption-text" itemprop="description">
		Otomie, pricess of the Otomie, together with Thomas Wingfield.
	</figcaption>
</figure>

All the original attributes are in the new output, so there shouldn’t be any issues with missing styles or functionality.

View on Github Gists