I'm developing a client website with Wordpress (3.3) but have found that the image caption feature strips out any HTML tags.

The resulting caption is plain text which makes proper image crediting difficult. Also being a client website, WYSIWYG editing is required.

For example if my shortcode is:

[caption caption="This is my <em>example</em> caption"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>

The tags are stripped from the caption attribute like so:

[caption caption="This is my example caption"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>

The tags I'd most like to preserve are <em>, <sup>, <sub>, <span> and <a>.

I haven't found any existing plugins to fix this except for links.

Any ideas on how to go about this and which functions to override?

  • It probably won't help now, it does look like this will be fixed for 3.4: Support HTML in image captions - core.trac.wordpress.org/ticket/18311 – Dave Romsey Jan 17 '12 at 5:34
  • use html5 figcaption ;) – petermolnar Jan 17 '12 at 13:27
  • As you are new here, mnorrish, be advised that you should upvote answers you like and accept the most useful one (by clicking the grey tick next to it). – Raphael Jan 17 '12 at 13:36
  • I like the figure/figcaption tags but found that switching between the Visual and HTML editors strips the <figure> tags. – mnorrish Jan 18 '12 at 1:56
  • Yea, WP does not really support HTML5 yet. :-/ – Raphael Jan 18 '12 at 10:00

I'm glad that better support should be added in version 3.4 but for now I've fixed the issue by changing the behaviour of image insertion so that it doesn't use the [caption] shortcode.

Here's what I added to functions.php:

add_filter( 'disable_captions', create_function('$a', 'return true;') );

function image_send_to_editor_2($html, $id, $caption, $title, $align, $url, $size, $alt) {
    if ( !$caption ) {
        return $html;
    } else {
        $width = 'auto';
        if ( preg_match( '/width="([0-9]+)/', $html, $matches ) ) {
            $width = $matches[1] . 'px';

        $output = '<div id="attachment-' . $id . '" class="wp-caption align' . $align . '" style="width: ' . $width . ';">';
        $output .= $html;
        $output .= '<p class="wp-caption-text">' . $caption . '</p>';
        $output .= '</div>';

        return $output;


add_filter('image_send_to_editor', 'image_send_to_editor_2', 10, 8);

This works best with the TinyMCE Advanced plugin with its option to stop removing (and adding) <p> and <br /> tags enabled.

  • Using <dl> for this purpose strikes me as odd, especially from a semantic viewpoint. Also, it is not stable against changes to Wordpress and your preferences; if anything changes, you have to manually edit all prior posts or bear with broken/different looking posts. – Raphael Jan 18 '12 at 9:36
  • 1
    Oops that's right. It's only in the editor that a <dl> is used. I'll change this to a <div> for the container and <p> for the caption. – mnorrish Jan 18 '12 at 20:22

Okay, your problem seems interesting.

One thing I could think of is:

[caption caption="caption1"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>

Store a custom meta field for the post with name 'caption1' and your HTML caption. Use a filter on the_content() to convert all caption1 into your HTML caption by pulling it from postmeta.

  • This is a crowbar solution, but should be fine in most cases. Note that if you want to be able to use shortcodes in your caption, you will have do run do_shortcodes on the replacement string. Also, if you have other plugins that work on filter the_content you might get unexpected results depending on the order in which the registered functions are executed. – Raphael Jan 18 '12 at 9:40
  • I do not understand when you say I have to run do_shortcodes on the replacement string. If you are worried about the order of filters running on the_content you can choose a much specific caption name like mycap_capname to ensure that no other filters pick it up. Unexpected results can be easily avoided. – Sterex Jan 18 '12 at 12:27
  • Hm, my bad. Codex says that do_shortcodes is registred on the_content, too, with priority 11. So as long as you add your filter with priority at most 10, you are fine. – Raphael Jan 18 '12 at 14:09

First of all, you can put stuff into captions like that:

[caption ...]
  <a ...> ... </a>
  Your caption text

This works with most formatting HTML. It fails (iirc) for links, and it also might not place the caption exactly the way you like it.

I have observed that stuff produced by shortcodes in captions is not sanitised, though. Therefore, my workaround uses the excellent and ever useful plugin Shortcode Exec PHP and create a shortcode captiontext with this PHP:

return '<div style="text-align: center; margin: 5px 0px -20px 0px;">'.do_shortcode($content).'</div>';

Adjust styling information to your liking, obviously. Now you can use it like this

[caption ...]
  <a ...> ... </a>
  [captiontext]Your caption text[/captiontext]

and you can use all the HTML you want.

Edit: Advantages of this solution: It is (relatively) stable against future changes in Wordpress and your taste. As long as shortcodes are handled the way they are now, you can adjust your shortcode definition to compensate whatever changes in all posts ever written without having to touch every single one of them. Furthermore, the workaround is nicely integrated into Wordpress' natural flow; in particular, you can use other shortcodes in your caption. Last but not least, you do not have to touch any theme or core file for the workaround but use a mature plugin instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.