Heyo! I'm Matt Brett, a freelance web designer living in beautiful BC, Canada. I specialize in WordPress development and generally making things that are awesome. When I'm not working, I'm playing video games, and I've published 133 game reviews over the past few years.

WordPress Post Thumbnails Revisited

Shortly after the release of WordPress 2.9, I published my technique for bulletproof post thumbnails. Since then, it’s evolved yet simplified into a more robust solution, specifically for use in WordPress themes. The problem, was that each image uploaded was generating a new set of images in various sizes, on top of the three that WordPress creates by default. This resulted in 6 or 7 images, instead of just a handful. While this isn’t really a huge deal, it means you’re going to be using more space on your server, and the uploads directory will get a bit unruly.

From the Ground Up

I’m going to assume you haven’t read my original article, and aren’t familiar with implementing post thumbnails in a WordPress theme. The first step, is to activate post thumbnails in your functions.php template. If you don’t see functions.php in your theme directory, create one.

if (function_exists('add_theme_support')) {
	add_theme_support('post-thumbnails');
}

Note: If you’re creating a new functions.php template, you’ll need to wrap that in a php tag.

Dynamic Image Resizing Instead of Physical Files

At this point, you’re able to create additional images at various sizes, but that’s where this implementation differs from the original. Instead of having WP create physical files on upload, we’re going to use the TimThumb image resizing script to create the new image sizes on the fly. Download the latest version of TimThumb and add it to your theme directory. Now, create a directory named “cache” and make sure it has appropriate write permissions (755 or 777, depending on your server), also in your theme directory.

For Theme Developers

Theme developers have to try and anticipate every situation to ensure their product works for as many people as possible. Because of this, the implementation that’s used in my themes is still pretty complex. I’m now in the habit of creating a file to include where thumbnails are present, and would suggest you do the same.

<?php
	// Checks to see if there is a post thumbnail, or image specified via custom field
	if (has_post_thumbnail() || get_post_meta($post->ID, 'post_image_value', true)) {
		// Opens a container called post-tnail and accompanying link to enclose the image
		echo '<div class="post-tnail"><a href="'.get_permalink().'" title="'.get_the_title().'">';
		// Creates a function for both methods of attaching images to posts for inclusion later on
		$thumbnail = wp_get_attachment_image_src(get_post_thumbnail_id(), 'large');
		$postimage = get_post_meta($post->ID, 'post_image_value', true);
		// If the post thumbnails function exists, there is a post thumbnail assigned, and image resizing is enabled
		if ((function_exists('has_post_thumbnail')) && (has_post_thumbnail() && $mb_resize == 0)) {
			echo '<img src="'.get_bloginfo('template_url').'/thumb.php?src='.$thumbnail[0].'&amp;w=150&amp;h=110&amp;zc=1&amp;q=95" alt="'.get_the_title().'" />';
		}
		// Or if the post thumbnails function exists, there is a post thumbnail assigned, and image resizing is disabled
		else if ((function_exists('has_post_thumbnail')) && (has_post_thumbnail() && $mb_resize == 1)) {
			echo '<img src="'.$thumbnail[0].'" alt="'.get_the_title().'" />';
		}
		// Or if the post thumbnails function does not exist and there is no post thumbnail, but there is a custom field image, and image resizing is enabled
		else if (get_post_meta($post->ID, 'post_image_value', true) && $mb_resize == 0) {
			echo '<img src="'.get_bloginfo('template_url').'/thumb.php?src='.$postimage.'&amp;w=150&amp;h=110&amp;zc=1&amp;q=95" alt="'.get_the_title().'" />';
		}
		// Or if the post thumbnails function does not exist and there is no post thumbnail, but there is a custom field image, and image resizing is disabled
		else if (get_post_meta($post->ID, 'post_image_value', true) && $mb_resize == 1) {
			echo '<img src="'.$postimage.'" alt="'.get_the_title().'" />';
		}
		// Closes the surrounding link and container
		echo '</a></div>';
	}
?>

If your theme doesn’t have an option for disabling image resizing, you can use this simplified version…

<?php
	// Checks to see if there is a post thumbnail, or image specified via custom field
	if (has_post_thumbnail() || get_post_meta($post->ID, 'post_image_value', true)) {
		// Opens a container called post-tnail and accompanying link to enclose the image
		echo '<div class="post-tnail"><a href="'.get_permalink().'" title="'.get_the_title().'">';
		// Creates a function for both methods of attaching images to posts for inclusion later on
		$thumbnail = wp_get_attachment_image_src(get_post_thumbnail_id(), 'large');
		$postimage = get_post_meta($post->ID, 'post_image_value', true);
		// If the post thumbnails function exists, there is a post thumbnail assigned
		if ((function_exists('has_post_thumbnail')) && (has_post_thumbnail())) {
			echo '<img src="'.get_bloginfo('template_url').'/thumb.php?src='.$thumbnail[0].'&amp;w=150&amp;h=110&amp;zc=1&amp;q=95" alt="'.get_the_title().'" />';
		}
		// Or if the post thumbnails function does not exist and there is no post thumbnail, but there is a custom field image
		else if (get_post_meta($post->ID, 'post_image_value', true)) {
			echo '<img src="'.get_bloginfo('template_url').'/thumb.php?src='.$postimage.'&amp;w=150&amp;h=110&amp;zc=1&amp;q=95" alt="'.get_the_title().'" />';
		}
		// Closes the surrounding link and container
		echo '</a></div>';
	}
?>

For Use in Personal or Client Themes

Things get a lot easier when you don’t have to worry about potentially hundreds or thousands of people using your theme. When I’m building a theme for a client, this new implementation that relies on TimThumb for dynamic resizing is much simpler.

<?php 
	$thumbnail = wp_get_attachment_image_src(get_post_thumbnail_id(), 'large');
	if (has_post_thumbnail()) {
		echo '<div class="post-tnail"><a href="'.get_permalink().'" title="'.get_the_title().'"><img src="'.get_bloginfo('template_url').'/thumb.php?src='.$thumbnail[0].'&amp;w=150&amp;h=110&amp;zc=1&amp;q=95" alt="'.get_the_title().'" /></a></div>';
	}
?>

As you can see, there are no checks to see if image resizing is enabled, or if there are legacy images present, or if the site is even running a compatible version of WP. All of these factors are known, so there’s no need to worry about all of the fall-backs.

Make Sense?

This new implementation, while still backwards compatible, is more future proof than the previous one. But in some cases, the original implemtation is a better fit. Especially if you’re running a fairly high-traffic site. The TimThumb script can be costly as far as server resources are concernced, and you might incur extra load time.

8 Comments

  1. Hey Matt,

    I don't know if this is of any interest to you but a colleague suggested using urlrewrites to tidy up the urls of the images so that they don't have the query stuff in.

    So you could have

    /images/thumbs/someimage.jpg that would rewrite to

    /thumb.php?src='.$thumbnail[0].'&w=150&h=110&zc=1&q=95

    If that makes sense.

    There might be a few problems with caching so maybe add a timestamp to the url to stop the browser caching it.

    I thought it was a cool idea anyway.

    Johny

    • Indeed, that's an interesting thought. I'm not sure if there would be any concerns with caching, as I'm not overly familiar with URL rewriting. I wouldn't think this would be overly necessary, though. You only see the image paths if you view the source.

  2. What do you think about the performance of generating dynamic images? I've used this approach before with a few Rails, Django, and CakePHP apps I've built (no WordPress sites though), but I've always ended up going back to generating image sizes on upload.

    Did you find that there was any noticeable slowdowns when viewing a site using this approach?

    • Hey Jeff, I've recently moved all static content on my site over to a CDN, and now use CSS sprites instead of individual images to minimize requests etc… The upshot of this is dynamically generated images using timthumb on WordPress are by far the slowest loading part of the site. So I too am considering moving back to pre-sized images.

      However, this post came just at the right time for me Matt, as I'm adding post thumbnails to my latest public theme – where optimisation isn't such a high priority :)

    • Yeah, performance can be an issue, especially with busier sites. I added a couple sentences to the closing paragraph to make mention of this. The original implementation is still a good one, and is better suited for certain situations.

      The major drawback, is being held to the sizes that the images were sized to on upload for the foreseeable future. This is especially a problem for people that change their theme often.

      • I ran into the sizing issue as well when I was working on my last site redesign and ran across the Regenerate Thumbnails plugin which ended up working out pretty well for me. One thing to note though is if you have done any cropping or editing within WordPress on any of your images, it'll be wiped out by the plugin and have the default crop settings applied.

        • Nice find! I was looking for something like that when I wrote my initial article on this subject.

          I would be a little hesitant to instruct my theme customers to use such a thing, though. There seem to be a fair amount of people on the wordpress.org forums with problems. But this is definitely something I could use myself, and with client projects.

  3. Thanks Matt! This article is very useful. I have a question though. Would you happen to know what code to use if no post-thumbnail nor custom post-thumbnail? I read your previous post, bulletproof post thumbnail and you included the code below. I tried to add that but its not working with code you provided in this post.

    // Or if neither Post Thumbnail nor custom field post image have been specified

    else {

    echo '';

    }

Sorry, Comments Are Closed

Comments are automatically closed on posts older than 365 days. If you have something you'd like to contribute, feel free to hit me up on Twitter.