Automatically display images in WordPress themes

Want to automatically display an image for each post in your custom WordPress theme without resorting to custom fields or asking the writer to jump through any hoops? How about displaying one size on the home page and another for the “single” pages?

One thing I’ve wanted to do a few times when designing WordPress themes is to automatically display an image for each post (if one has been uploaded). As far as I know, WordPress doesn’t currently have a convenient way of doing this built-in, but it’s quite easy to write the function into your custom theme.

First, you need to configure the WordPress settings to choose the size of your thumbnails. For this example, I set the small thumbnail to 64 x 64 pixels and clicked the crop option.

Inside the post loop, simply insert this code. It’ll grab the first image listed in the database associated with the current post. Then, in this case it looks for the thumbnail that’s been automatically sized to 64×64 pixels and stores the results in the variable $image for automatic use in your theme.

$image = "";
$post_attachments = $wpdb->get_results("SELECT guid "
."FROM $wpdb->posts "
."WHERE post_parent = '$post->ID' "
."AND post_type = 'attachment' "
."ORDER BY `post_date` ASC "
."LIMIT 0,1"

if ($post_attachments) {
$image = $post_attachments[0]->guid;
$image = str_replace(".jpg","-64x64.jpg",$image);
$image = str_replace(".png","-64x64.png",$image);
$image = str_replace(".gif","-64x64.gif",$image);
# Do something with the $image

Say, however you’d rather load your medium sized image automatically. First, set your thumbnail size to your preferred dimensions.

Then the code is slightly trickier since we can’t infer the exact filename by knowing the thumbnail size since only one dimension is going to match. So, we build the filename with what we know, and then use the glob command to list the filename that matches:

$image = "";
$post_attachments = $wpdb->get_results("SELECT guid "
."FROM $wpdb->posts "
."WHERE post_parent = '$post->ID' "
."AND post_type = 'attachment' "
."ORDER BY `post_date` ASC "
."LIMIT 0,1" );

if ($post_attachments) {
$sourceimage = $post_attachments[0]->guid;
# pick up the image with size 470 if one exists
$sourceimage = str_replace(".jpg","",$sourceimage);
$sourceimage = str_replace(".png","",$sourceimage);
$sourceimage = str_replace(".gif","",$sourceimage);
foreach (glob("$root$sourceimage-*470*") as $filename) {
$image = $filename;
$image = str_replace("$root","",$image);

This method is a fairly user friendly, allow you to wrap your images in links or other formatting commands in your theme without burdening your users with manually entering code every time. I also found the Regenerate Thumbnails plugin useful when retro-fitting old sites with this upgrade.

I’d love to hear your thoughts or if you find it useful for your theme.

This Post Has 15 Comments

  1. Thanks for the article. I was looking to learn how to do this exact thing and found this with google. I will give it a try tomorrow. Thanks.

  2. I’ll be interested to hear how it works for you. Good luck!

  3. Perfect! Its work like a charm. Thanks for hack.

  4. Thanks for the article.

    I’m trying to use this technique with the SEO Siloing plugin to draw my posts onto the page with thumbnails. I’m having trouble merging the two and would REALLY appreciate any help.

    1. @Travis: Unfortunately, I’m not too familiar with that plugin. Maybe the plugin author would want to add this feature for you? I’m considering packaging this little hack up as a plugin myself, but haven’t gotten around to it yet.

  5. Thanks for a great idea. I’ve been tweaking this for my purposes, and now have this function (I hope the code tag works here!):

    function getThumbnail( $postID, $size = "thumbnail" ) {
        global $wpdb;
        $image = "";
        $maxWidth = get_option( $size.'_size_w' );
        $post_attachments = $wpdb->get_results( "
            SELECT  guid
            FROM        $wpdb->posts
            WHERE       post_parent = $postID
            AND     post_type   = 'attachment'
            ORDER BY    post_date ASC
            LIMIT       0,1
        " );
        if ( $post_attachments ) {
            $sourceimage = $post_attachments[0]->guid;
            $sourceimage = str_replace( ".jpg", "", $sourceimage );
            $sourceimage = str_replace( ".png", "", $sourceimage );
            $sourceimage = str_replace( ".gif", "", $sourceimage );
            $sourceimage = str_replace( get_bloginfo( "siteurl" ), "", $sourceimage );
            $root = $_SERVER[ 'DOCUMENT_ROOT' ];
            foreach ( glob( "$root$sourceimage-*$maxWidth*" ) as $filename ) {
                $image = $filename;
                $image = str_replace( $root, "", $image );
        return $image;

    It defaults to getting the thumbnail, or you can ask it to get the medium size, too. It dynamically gets the WP option for the relevant max width and matches on that.

    This function works for my current set up – both thumbnail is set to 80 x 80 and medium is set to 150 x 150. The match allows the max width value found to be anywhere in the filename, i.e. it could end up matching the height of a thumbnail, if you have thumbnail at 80 x 150 and medium as 150 x 300, say. Not sure – please test for yourself before using, but hopefully this idea is of use to someone…

  6. Even better, WordPress does actually have built-in functions to handle this. I just discovered:

    There’s more functions along similar lines. My revised function, to return the specified size (“full”, “medium”, “thumbnail”) of the image in the specified post or page, is as follows:

    function getImage( $postID, $size = "thumbnail" ) {
        $images = get_children( "post_parent=$postID&post_type=attachment&post_mime_type=image" );
        if ( $images ) {
            foreach( $images as $image_id => $image_infos ) {
                $the_image = wp_get_attachment_image_src( $image_id, $size );
                if ( $the_image ) {
                    return $the_image[0];
        return "";
    1. This looks like a nice improvement. I’m going to give it a try too.

      Thanks a lot.

  7. It’s not working for me. Can you please clarify the following in your explanation above?

    1. What exactly do you call “Post Loop”. I assume you refer to the single post template in the theme design. If you do, can you specify exactly where to insert this code?

    2. What do you mean by “database associated with the current post”? Where is this database located?

    Thanks a lot.

  8. Hi Mario,

    The post loop is the part of the template that starts with something like:

    while ($the_query->have_posts()) : $the_query->the_post();

    and ends with:

    Regarding the database associated with the current post, it simply refers to the images that have been uploaded along with the current post. This information is stored in the database–you don’t have to worry about that if it doesn’t make sense to you.

    Best of luck.

  9. Hi, thanks for replying. I set the size of thumbnails and medium, placed the code inside the loop, then wrote a post and uploaded a thumb photo. Is that thumbnail supposed to upload automatically in future posts, because it doesn’t in mine. What am I doing wrong? Thanks

  10. Actually, my code is designed to display the first uploaded image for each post individually–not automatically display an image for future posts. If you’re looking to display the same image for every post, you can do that without any of the fancy code above, just by adding the appropriate img html code to your template.

  11. Hello I use your plugin through autofocus theme, but i have a problem. In some posts, my image doesn’t appear.Could you tell me where is the pb? The error message is : Thank you Nadege

    1. Thanks for writing. I’m not sure the specific configuration you’ve got, but that “error message” you are seeing is intended–as it removes the first image in a post so that the theme can automatically display it. You also might check out the latest version of Autofocus as I don’t think it needs that plugin at all.

Comments are closed.

Close Menu