I'm working on building out a custom theme and have been struggling with this one for a bit. I am trying to modify the HTML output of the_post_thumbnail(); function. I need to do this because I am trying to support retina images on my site and would rather bake the functionality into my theme than load a plugin on the backend.

By default, the_post_thumbnail(); merely calls get_the_post_thumbnail(); which I found here. My first thought was to plug into the 'post_thumbnail_html' filter, but I can't seem to get it working. So...

This is how I'm calling my post thumbnails in the loop:

<?php the_post_thumbnail('custom-thumbnail-size', array('class' => 'unique-class-here', 'title' => 'unique-title-here')); ?>

This is the code I need output when I call the_post_thumbnail();...

<img src="" alt="" data-src="image.png" data-alt="Alt text" class="retina unique-class-here" />

And the below code is what I currently have in my functions.php file:

function modify_post_thumbnail_html($html, $post_id, $post_thumbnail_id, $size, $attr) {
    $src = wp_get_attachment_image_src(get_post_thumbnail_id(), $size);
    $html = '<img src="" alt="" data-src="' . $src['0'] . '" data-alt="" class="retina" />';
    return $html;
add_filter('post_thumbnail_html', 'modify_post_thumbnail_html', 99, 5);

A couple things to note. I am not sure how to pass in the appropriate metadata text in the 'data-alt' attribute. Also, I need to be able to pass the specific post_thumbnail size I need since I use custom post_thumbnail sizes throughout my theme. Lastly, you can see the attribute array needs to pass in classes in addition to the default 'retina' class as well as any other attributes in that array.

Thanks in advance for any help. There's really not much online about this topic and I figured my question was different enough to warrant an additional post to this community. Please let me know if you have any thoughts, solutions and/or need any clarifications.

3 Answers 3


Ok, so I think I may have come to a solution. It doesn't seem as nice and easy as I'd like it to be, but then again major modifications to default Wordpress functionality sometimes requires drastic measures. :)

This is my working solution to rewriting the HTML output for post thumbnails throughout my site to work with the Retinise.js plugin. Of course this code may be adapted for other post thumbnail HTML manipulations.

In my functions.php file, I created this function:

function modify_post_thumbnail_html($html, $post_id, $post_thumbnail_id, $size, $attr) {
    $id = get_post_thumbnail_id(); // gets the id of the current post_thumbnail (in the loop)
    $src = wp_get_attachment_image_src($id, $size); // gets the image url specific to the passed in size (aka. custom image size)
    $alt = get_the_title($id); // gets the post thumbnail title
    $class = $attr['class']; // gets classes passed to the post thumbnail, defined here for easier function access

    // Check to see if a 'retina' class exists in the array when calling "the_post_thumbnail()", if so output different <img/> html
    if (strpos($class, 'retina') !== false) {
        $html = '<img src="" alt="" data-src="' . $src[0] . '" data-alt="' . $alt . '" class="' . $class . '" />';
    } else {
        $html = '<img src="' . $src[0] . '" alt="' . $alt . '" class="' . $class . '" />';

    return $html;
add_filter('post_thumbnail_html', 'modify_post_thumbnail_html', 99, 5);

Then, whenever I call the_post_thumbnail(); in a WP loop, I use this code:

<?php the_post_thumbnail('custom-thumbnail-size', array('class' => 'retina additional-class')); ?>

This code should work (obviously with minor modifications) if you're operating outside of a WP loop. Hope this will save someone else some time and frustration! Maybe when I get around to it, I'll post a complete start to finish Q & A on how I baked in retina support to my theme. No plugins used!

Here's a few links to point someone in the right direction if interested!


hackish solution:

since wordpress add a lot of classes by default to the <img>, if you don't change that behaviour by force, you can always 'inject' something via str_replace before the string class=. In code:

$image = get_the_post_thumbnail( $post->ID, 'medium', array( 'class' => 'myclass' ) );
$moreattrs = 'data-fullimg= "full.jpg"';

$image = str_replace('class=', $moreattrs.' class=', $image );

It's pretty safe to assume that if something starts with "class=", that's what you want. Of course, it could be messed up by weird filenames containing that class=, but especially with wordpress, that's highly unlikely.

you could also search for <img and replace that; thinking about it, I guess that should be a bit safer.

  • Is there a way to do this to all images automatically? some hook which can fire just before the page HTML has been rendered?
    – vsync
    Apr 11, 2018 at 19:35

Maybe you could hook into wp_get_attachment_image_attributes :

function my_custom_image_attributes( $attr, $attachment ) {
  $image = wp_get_attachment_image_src( $attachment->ID, 'full' );
  $attr['data-src'] = $image[0];
  $attr['data-alt'] = $attachment->post_title;
  $attr['class'] .= ' retina';
  return $attr;

This needs to be tested and maybe amended, I found the idea here Add class name to post thumbnail (check for vwp_get_attachment_image source code at the end).

You need to add the hook just before calling the_post_thumbnail() in your theme.

Also, I don't know what you need to use as data-alt, in my opinion, you could use a field of the attachement that passes with the filter (it could be a custom field).

  • Hi @Simon. Thanks for your response!! Unfortunately, I cannot get the above working. A quick Google search reveals that almost everyone is having issues with the 'wp_get_attachment_image_attributes' hook. Is there maybe another hook that would work? That's why I went the 'post_thumbnail_html' route, I just cannot figure out how to get the attributes to pass correctly from my the_post_thumbnail('custom-thumbnail-size', array('class' => 'unique-class')); call. Any further thoughts?
    – kaffolder
    Feb 9, 2014 at 22:39
  • Not immediately. I need to do some test first, but I think it's doable. At first look, you need to use $attr['class']
    – Simon
    Feb 9, 2014 at 23:05
  • I posted a working solution above. Not sure if it's best-practice or not. Let me know if you find a better/alternative solution. Thanks!
    – kaffolder
    Feb 9, 2014 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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