How do I change/modify the_post_thumbnail(); html output?

The question:

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:

<?php
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.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

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:

<?php
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!

Method 2

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.

Method 3

Maybe you could hook into wp_get_attachment_image_attributes :

function my_custom_image_attributes( $attr, $attachment ) {
  remove_filter('wp_get_attachment_image_attributes','my_custom_image_attributes');
  $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;
}
add_filter('wp_get_attachment_image_attributes','my_custom_image_attributes');

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).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment