Grow your CSS skills. Land your dream job.

Last updated on:

Get The First Image From a Post

Let's say you wanted to use the post thumbnail feature of WordPress, but had a whole archive of posts that would take too much time to go through. For new posts, you can be specific and use the feature as intended. For old posts, you just want to use the first image it finds in the content for the thumbnail, or a default if none present.

Add this to functions.php or make a functionality plugin:

function catch_that_image() {
  global $post, $posts;
  $first_img = '';
  ob_start();
  ob_end_clean();
  $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
  $first_img = $matches[1][0];

  if(empty($first_img)) {
    $first_img = "/path/to/default.png";
  }
  return $first_img;
}

To use it, use this code in the loop:

if ( get_the_post_thumbnail($post_id) != '' ) {

  echo '<a href="'; the_permalink(); echo '" class="thumbnail-wrapper">';
   the_post_thumbnail();
  echo '</a>';

} else {

 echo '<a href="'; the_permalink(); echo '" class="thumbnail-wrapper">';
 echo '<img src="';
 echo catch_that_image();
 echo '" alt="" />';
 echo '</a>';

}

I found that has_post_thumbnail wasn't as reliable as the logic above.

Reference URL

Comments

  1. Reece
    Permalink to comment#

    Thanks for this. Always on the lookout to add functionality to WP.

    Best,
    Reece

  2. TomTank4
    Permalink to comment#

    Great function, I am trying to add youtube functionality to this but am a bit stuck.

    I wanted it to grab the youtube thumbnail if it sees a youtube embed before it sees an image. Any ideas?

    • I’m not familiar with how to make things work in WordPress – – – but I included similar functionality in my Journal which I recently rewrote (hand coded – not WordPress). It is based on my use of the iFrame Video Embed for HTML5 compatability in my Journal – so won’t work with object and embed code. Hopefully you can use it and adapt it to your WordPress application in a similar way as above with the first image.

      This video check code, comes after I have checked to see if there is an image in the content from a post (as I loop through). If it finds an iframe, it uses preg_match to extract the “src” of the iframe – and if there is a match to ‘www.youtube.com’ – I can create a url based on the video id that is extracted from the src url.

      This is one of the pages that contains a couple of posts with Youtube video – where I got the Youtube images and display them – http://robertwatcher.com/journal/index.php?crnt=9

      
      preg_match('|<iframe [^>]*(src="[^"]+")[^>]*|', $postcontent, $matches);
      $tmp_src = explode('/',$matches[1]);
      $vid_id = rtrim($tmp_src[count($tmp_src)-1], '"' );
      if($matches AND $tmp_src[2]=='www.youtube.com'){
      	$youtube_img_url = 'http://img.youtube.com/vi/'.$vid_id.'/hqdefault.jpg';
      	echo '<img src="'.$youtube_img_url.'" alt="You Tube Video" />';
      }
      

      I have left out the extra if statements that check next for a Vimeo video url (which requries more complex code to extract) , as well as a default image if there is not a src url.

  3. Anon
    Permalink to comment#

    I have this in a page kind of like a small gallery but its limited due to:

    Settings >> Reading >> Blog pages show at most

    Is there a way around this to grab all images no matter what the limit is from settings?

  4. Permalink to comment#

    I’ve been using the functions.php version of the code for a while now, but only recently discovered that this doesn’t seem to work for pages. Any chances there’s a way to make it apply to them as well?

  5. Hi, i would like to ask what if i want to get the second image instead of the first one? Helps are much appreciated thanks

  6. That’s a great piece of code, thanks for sharing.

    I have a question though – if you were doing this from an attachment page (attachment.php) what would you change in the function to make it output correctly?

    Thanks.

    Paul.

  7. Carlos Goncalves

    How Can I change the image size?

    • Permalink to comment#

      You should use some css:

      .thumbnail-wrapper img {width:300px;}

      If you want it to resize with the page use something like:

      .thumbnail-wrapper img {width:60%;}

  8. george
    Permalink to comment#

    Does anybody know how to get the first occurance of firstbigimage_big.jpg from:

    Imgur

    thanks

  9. Suwandi Halim
    Permalink to comment#

    Thanks. Help my day.

  10. Permalink to comment#

    I found this high up in Google search, what a joke.

    Someone on css-tricks.com should manage the snippets to not promote garbage code, preg matching the content for images tags..?..?

    WordPress already has a simple built in function for this called: get_children

    • For anyone reading this troll’s post and is worried about it…

      get_children gets images that are associated with the post. Like you used the built in image uploader to upload the image. That’s not always the case, hence needing to parse for it (e.g. an embedded flickr photo).

    • Walter
      Permalink to comment#

      @chris no, get_children() gets thumbnails associated to a post. This code extracts from post content the first img html tag.

    • BUURRNNNN

  11. Steve
    Permalink to comment#

    Great tutorial. I would also like to know how to leverage this code to offer a dynamically sized image. It seems folks are using timthumb for this, I’m curious if there is a way to do it with core WP functions.

    It’s mentioned above that CSS can be used, but that’s not a great approach if you need to resize an image more than a few pixels. The goal is to deliver the image in a new size similar to how get_the_post_thumbnail($post->ID, array(80,80)); works. Thanks!

  12. Tori
    Permalink to comment#

    Thank you so much! I don’t know why after all this time, I just don’t check your page first when it comes to WordPress.

  13. nev
    Permalink to comment#

    I’d love to know how to use this logic in a child theme. I’ve hacked my child theme’s content.php so far to enable excerpts in the loop, but I’d really like the excerpt to show the first image in the post as well. Not got into making plugins yet, so I was hoping there might be a way, either by modifying my child theme’s content.php and/or its functions.php (crosses fingers) ;)

  14. nev
    Permalink to comment#

    OMG I did it! Thanks TONS for this code!!!

  15. nev
    Permalink to comment#

    This code is gold! It picks up the image if it’s a featured image or not. Brilliant! Thank you!!!

  16. Steph
    Permalink to comment#

    This is a great snippet, thanks for posting it.

    Just curious if anyone has successfully altered the function to return no IMG tag if no image is found instead of a placeholder? I’ve been tinkering with it but no joy, my PHP is rusty sadly.

  17. flo
    Permalink to comment#

    great! what would be the code in order to show the LATEST image attached to a post. best, flo

  18. Barry
    Permalink to comment#

    For some reason this always gets the last image in a post and not the first. Used as is with a few posts with about 2 images in each.

  19. nev
    Permalink to comment#

    @Barry – That’s strange – it’s taking the first image for me (i.e., the first image that appears in the post – the one nearest the top).

    I’m inserting the code inside a duplicated content.php in a child theme, directly after:

    <

    div class=”entry-summary”>

    … in its own div.

    Seems to work for me.

  20. nev
    Permalink to comment#

    Just one problem – it returns the first image for listings in the loop, but not for category listings

  21. nev
    Permalink to comment#

    sorry – I meant, not for category listings where the first image is a featured image (I know I could get the first non-featured image, but I wondered if it could be tweaked to get the first featured image for category listings?

  22. nev
    Permalink to comment#

    Ah – I worked it out – just to add:

    || is_category()

    … to the conditional.

    Duh!

  23. Permalink to comment#

    Is there anyway we can display an image for Only First Post?

  24. nev
    Permalink to comment#

    There’s a problem with the default image path when viewing category listings with pretty permalinks turned on – you get a broken image link because something like “images/default.jpg” is appended to the end of the permalink (e.g., “example.com/category/images/default.jpg”).]

    Trying to think of a path to use that would cover all bases for that situation.

  25. I tried the code; it did return the image …

    p.s. I wrote my posts using windows live writer 2012 and embed Facebook photo link in live writer)

    But I couldn’t get the returned image in thumbnail size… Also, the image appears on top of the posts on both the index and individual post.

    That makes two images (one thumbnail and a duplicate one inside the post)..
    . I’d like to get rid of the thumbnail when it’s in single post while only showing the thumbnail with float left on index page.

    What can I do?

    I am using my own child theme from twenty twelve …

    Many thanks in advance…

  26. Thanks! Works like a charm :)

  27. This is how I handled it without regular expressions. I just put it in the template (in the loop of an archive page), but it wouldn’t be too hard to pull it into a function that could then be called in the template.

    <?php // Get thumbnail image
    
        if (has_post_thumbnail()) { 
            the_post_thumbnail('portfolio-thumbnail');
        } else {
            $gallery_arguments = array(
            'post_type' => 'attachment',
            'post_mime_type' => 'image',
            'post_parent' => $post->ID,
            'numberposts' => 1);
    
            $gallery_images = get_children($gallery_arguments);
            if ($gallery_images) {
                foreach ($gallery_images as $post) {
                $image_attributes = wp_get_attachment_image_src($post->ID,'thumbnail');
                ?>
                    <img src="<?php echo $image_attributes[0]; ?>">
            <?php } }
                wp_reset_postdata();
        };
    ?>
    
    • Mittens

      I actually got to this page because I was doing something similar to what you have.

      I really liked that way, however get_children will only work if said image is only used in the current post. Or at least that’s where it was used first.
      That’s because in the current WP version, post_parent has to be unique (an attachment can’t have multiple parents).

      Solutions to this can however be obtained by hacking around with plugins that duplicate attachment entries in the database for each new post (see here).

      Are you using any of those solutions?

  28. Hi guys,

    I am using a foundations theme and have followed the exact steps above. It works on the localhost (links to images in the right localhost path). The problem comes in on the live, the images path is that from the localhost:

    http://localhost/MySite/wp-content/uploads/2013/06/corrupt.jpg

    So basically it breaks. How to I turn the localhost url into a more dynamic one?

  29. Dan Gaz
    Permalink to comment#

    Perfectly Working! :) Many ThanX

  30. Permalink to comment#

    I’m currently give up with the_post_thumbnail(); function at all and moving to use first_img instead from duplicate my work making thumbnail and inside post image ..

  31. Wendy
    Permalink to comment#

    I’ve been using this function for a while, now noticing that I’m getting a php notice in my error log, PHP Notice: Undefined offset: 0. for this line: $first_img = $matches [1] [0]; This post here: http://stackoverflow.com/questions/9399509/getting-rid-of-php-notice-undefined-offset tells me I need to use isset() to check if something is in there first. Has anyone else experienced this? I’m only noticing this notice now, wondering what may have changed.

  32. DUKE
    Permalink to comment#

    i have a problem the default img not show & it show me the error:

    Notice: Undefined offset: 0 in /vagrant/wp-content/themes/advocacy/functions.php on line 51 http://127.0.0.1:8080/wp-content/themes/advocacy/assert/img/ipa.no.list.img.jpg

    line 51: $first_img = $matches[1][0];

    can someone help me?

    • DUKE
      Permalink to comment#

      I found a solution that works for me:
      REPLACE:

      $output = preg_match_all(‘/<img.+src=\'”[\'”].*>/i’, $post->post_content, $matches);
      $first_img = $matches[1][0];

      with:

      if( $output = preg_match_all(‘/<img.+src=\'”[\'”].*>/i’, $post->post_content, $matches) )
      {
      $first_img = $matches[1][0];
      }

  33. Permalink to comment#

    i am trying this.. but instead of getting image. i am getting only the link… can any one help me on this

  34. Jones
    Permalink to comment#

    This code looks very similar to an answer provided on StackOverflow.

  35. Carol Ann
    Permalink to comment#

    Hello,

    I’m not a programmer, but think I have stumbled upon your post looking for the right thing and was hoping you could help me integrate your code into the following code in my theme?

    Thanks in advance :)

    if ( has_post_thumbnail() )  ?>
    
        <div class="entry-image" style="<?php echo $max_height; ?>">
    
            <?php 
    
            if(!of_get_option('post_image_lightbox')){ ?>
    
                <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" rel="bookmark">
    
                    <?php the_post_thumbnail( $featured_image_size ); ?>
    
                </a><?php 
    
            }else{
    
                $src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'large', false, '' ); ?>
    
                <a href="<?php echo $src[0]; ?>" class="lightbox" title="<?php the_title(); ?>" rel="bookmark">
    
                    <?php the_post_thumbnail( $featured_image_size ); ?>
    
    
                </a><?php 
    
            } ?>
    
        </div><?php 
    
        }
    
  36. Mike
    Permalink to comment#

    Is there a way to bypass the featured image and take the image that is listed first in the content? I’m using a child theme of twentythirteen and for some reason it will not crop my images when reducing it to thumbnail size. It just squeezes it into 100×100. So I’m forced to use a 100×100 image for my featured image (because I need a thumbnail displayed on my home page. I want to display the full size image on my page that displays my posts.

  37. eklotan
    Permalink to comment#

    thanks a lot. It works. great helpful.

  38. shahroz
    Permalink to comment#

    Hello sir please tell me how to use the second part of your code i mean how to add that code in a loop,sir i am a newbie so please help me thanks

  39. Permalink to comment#

    This is great! Great fallback when no thumbnail is set. Thanks!

  40. Nikolas

    Hi there.
    Thank you for your code. I’ve used it to display 4-5 random posts along with their first image.
    The code works fine but I would like to get the images dynamically resized. Using CSS is not an option since the images on my website are quite big and therefore loading 4-5 full size images below each post would make the site slow.

    So, is there a dynamic way to resize the image?

    Thank you in advance for your help :)

  41. Not working in custom post types .any one please provide a solution to this

  42. hey guys,
    I was wondering , what would it be needed to make it retrieve more than just the first one. maybe the first 4 images…. ?

    I think the array must be modified but i don’t understand it much…
    thanksss

  43. Kevin Hower

    First, thanks for this code! Second, I had the same undefined offset problem as some others had. So, what I did was leave the output line alone but change what came after that to :

    $first_img = $matches[1][0];
    
      if(empty($first_img)) {
        $first_img = "/path/to/default.png";
      }
      return $first_img;
    

    in the function and then in my template i put this:

                &lt;a href=&quot;" &gt;
                  &lt;img src=&quot;" alt="" /&gt;
                </a>
    

    I need to add some styling, but I’m still learning so I was more concerned with function for now than the style part. It also fixes the issue of having a default image show when there’s nothing to show, which was bugging me.

  44. Kevin Hower

    Well, crud, this just isn’t my day apparently. I thought I had pasted my own code but apparenty I pasted the original .

    THIS is actually what I did in the function:

    if (!empty($matches[1][0]) ) {
    $first_img = $matches[1][0];
    } else {
    $first_img = “”;
    }
    return $first_img;

    Sorry for any confusion.

  45. What’s the purpose of the $posts variable and output buffering? I tried it without either one and it worked fine. Here it is bundled up with an img tag and an alt attr:

    /**
    

    * Return an HTML img tag for the first image in a post content. Used to draw
    * the content for posts of the “image” format.
    *
    * @return string An HTML img tag for the first image in a post content.
    */
    function icicle_get_first_image() {

    // Expose information about the current post.
    global $post;
    
    // We'll trap to see if this stays empty later in the function.
    $src = '';
    
    // Grab all img src's in the post content
    $output = preg_match_all( '//i', $post-&gt;post_content, $matches );
    
    // Grab the first img src returned by our regex.
    if( ! isset ( $matches[1][0] ) ) { return false; }
    $src = $matches[1][0];
    
    // Sanitize for output
    $src = esc_url( $src );
    
    // Make sure there's still something worth outputting after sanitization.
    if( empty( $src ) ) { return false; }
    
    // Grab and sanitize the post title as an alt.
    $alt = esc_attr( $post-&gt;post_title );
    
    $out = "";
    return $out;
    

    }

  46. Fabrício

    Hello, the code worked perfectly, however, I wonder how do I automatically generate a smaller image size, because it is loading the original image.

    I tried to do something like:

    add_image_size (‘thumb-medium’, 160, 140, true, array (‘center’, ‘top’));

    More unsuccessfully!

  47. Permalink to comment#

    Hello, I want to show excerpt with first 300 characters of the post, how can I do it?

  48. komar
    Permalink to comment#

    Thanks for this. work for me.

  49. okita
    Permalink to comment#

    I tried this and it worked, but I have a problem with the fact that sometimes the first image turned out to be a smiley because it is also started with tag. Is there any way to exclude smilies from being selected as the first image?

    Tried to read about preg_match and regex but it’s way beyond my comprehension since I’m not a programmer myself.

  50. hesham
    Permalink to comment#

    Very helpful and works like a charm

  51. Helen
    Permalink to comment#

    Thanks so much for this tutorial and the one on Functionality plugin! I made my first plugin with the help of your tutorial and am so happy :)

    You and your site are the best!

Leave a Comment

Posting Code

Markdown is supported in the comment area, so you can write inline code in backticks like `this` or multiline blocks of code in in triple backtick fences like this:

```
<div>Example code</div>
```

You don't need to escape code in backticks, Markdown does that for you. If anything screws up, contact us and we can fix it up for you.

*May or may not contain any actual "CSS" or "Tricks".