DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Awesome Image-Attachment Recipes for WordPress

Posted by on

Recently, I found myself on the front lines of WordPress’ somewhat complicated Media-Library system. The site that I was developing required a rather elaborate system of retrieving and displaying image attachments. So, using the latest version of WordPress (2.8.3 at the time), I found myself experimenting with as many template tags and custom functions as I could find. After much experimentation, I discovered the perfect solution, and along the way I collected a healthy collection of recipes for displaying image attachments and their various types of associated information.

In this DiW article, you will learn some tasty ways to include image-attachment information in your posts. From echoing the latest image path to displaying custom-sized image-links for all post attachments, this article should serve as an invaluable resource for anyone working with WordPress’ Media Library and its media-attachment functionality.

Basic display of gallery attachments

When displaying your images via the [gallery] shortcode, WordPress will display image-links for each image in the gallery. Each of these image-links points to the image-gallery page for that particular image. The image gallery is created by the image.php template if present in your theme files. Here is a basic way to display your gallery images from within the image-gallery loop:

<a href="<?php echo wp_get_attachment_url($post->ID); ?>"><?php echo wp_get_attachment_image($post->ID, 'medium'); ?></a>

This code will display a medium-sized image-link to the original image. To display an image attachment of a different size, replace the $size parameter in the wp_get_attachment_image() template tag. Accepted values are thumbnail, medium, large, or full. The actual dimensions of these sizes are determined by your preferences in the Media panel of the WordPress Admin.

Display the URL of the latest image attachment

Perhaps the most useful template tag for displaying image-attachment information is wp_get_attachment_url(). This function returns a full URI for an attachment file. If no attachment is found, a value of false is returned. Here are several ways to use this tag within the loop:

<?php // display the attachment URI for post with specified ID
echo wp_get_attachment_url(7); ?>

<?php // display the latest attachment URI for each post from within the image.php loop
echo wp_get_attachment_url($post->ID); ?>

<?php // display the latest attachment URI for each post from within the index.php loop
echo wp_get_attachment_url($attachment_id); ?>

The output of this tag is similar to the following for each attachment:

http://digwp.com/wp-content/uploads/2009/08/example.png

If you are using the image.php file to display your attachments, use the second recipe to display the latest URI for each post. If you are displaying your attachments from any other template file (e.g., index.php, single.php, etc.), use the third recipe and refer to this section of the article for the code required to generate dynamically the $attachment_id variable for the post ID.

Display the latest image attachment as an image

The wp_get_attachment_image() template tag is used to display the latest image attachment as an actual HTML image element. If no image attachment is found, a value of false is returned. Here are several ways to use this tag within the loop:

<?php // display medium-sized attached image for post with specified ID
echo wp_get_attachment_image(7, 'medium'); ?>

<?php // display the latest attached image for each post from within the image.php loop
echo wp_get_attachment_image($post->ID); ?>

<?php // display the latest attached image for each post from within the index.php loop
echo wp_get_attachment_image($attachment_id); ?>

The output of this tag is similar to the following for each attachment:

<img src="http://digwp.com/wp-content/uploads/2009/08/example.png" class="attachment-thumbnail" height="50" width="50">

The wp_get_attachment_image() template tag may be customized with the following parameters:

<?php wp_get_attachment_image($attachment_id, $size='thumbnail', $icon=false); ?>

  • $attachment_id — ID of the desired attachment. Not required if used within an attachment loop, otherwise, refer to this section to generate the ID for non-attachment loops.
  • $size — Size of the image shown for an image attachment: thumbnail, medium, large or full
  • $icon — (Optional) Use a media icon to represent the attachment. Default value: false.

Display the thumbnail of the latest image attachment

I couldn’t find any official documentation for the get_attachment_icon() template tag, but after some experimentation, it seems useful for displaying a thumbnail of the latest image attachment for each post. Here are some examples:

<?php // display image thumbnail for post with specified ID
echo get_attachment_icon(7); ?>

<?php // display image thumbnail for each post from within the image.php loop
echo get_attachment_icon($post->ID); ?>

<?php // display image thumbnail for each post from within the index.php loop
echo get_attachment_icon($attachment_id); ?>

The output of this tag is similar to the following for each attachment:

<img src="http://digwp.com/wp-content/uploads/2009/08/example.png" title="example" alt="example">

If using this tag within an attachment loop, such as in the image.php or attachment.php theme file, the post ID parameter is generated automatically. If using within a non-attachment loop, such as in the index.php or single.php theme file, refer to this section for the code required to generate dynamically the post-ID variable.

Other useful template tags for displaying image attachments

Here are some other useful template tags for displaying image attachments and their related information:

<?php // returns the URL for the latest attachment thumbnail
wp_get_attachment_thumb_url($attachment_id); ?>

<?php // returns an image representing the latest attachment file
wp_get_attachment_image_src($attachment_id, $size='thumbnail', $icon=false); ?>

<?php // returns an image-link or text-link to the latest attachment file or attachment page
wp_get_attachment_link($id=0, $size='thumbnail', $permalink=false, $icon=false); 

<?php // displays an image link to the latest attachment file
the_attachment_link($attachment_id); ?>

<?php // returns an image link to the latest attachment file
get_the_attachment_link($attachment_id);  ?>

<?php // returns a URI to the attachment page for the latest attachment
get_attachment_link($attachment_id);  ?>

See the next section for generating the values of the $attachment_id variable.

Dynamic generation of the post ID for non-attachment loops

If you are using any of the above recipes within a single.php, index.php, or any other non-attachment loop, you will need to include the following line of code to generate the ID for each post:

<?php global $wpdb; $attachment_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_parent = '$post->ID' 
AND post_status = 'inherit' AND post_type='attachment' ORDER BY post_date DESC LIMIT 1"); ?>

This code dynamically generates the $attachment_id variable that is used in some of the examples above. Here is an example showing how to display the latest attachment URI for each post from within the index.php loop:

<?php global $wpdb; $attachment_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_parent = '$post->ID' 
AND post_status = 'inherit' AND post_type='attachment' ORDER BY post_date DESC LIMIT 1"); 
echo wp_get_attachment_url($attachment_id); ?>

Enough of the simple stuff! Let’s move on to some more advanced recipes.

Display all attachments for each post

Up to this point, we have been using template tags to display information related to the latest attachment only. With any of the above methods, the output for any of the template tags represents a single attachment item. In order to display multiple attachments for each post, we need to employ WordPress’ get_children() functionality. The get_children() tag returns an associative array of posts with post IDs as array keys. The default parameters are as follows (as of version 2.7):

$defaults = array( 
	'post_parent' => 0,     // get children of this post ID; null value gets all children
	'post_type'   => 'any', // post type: attachment, page, revision, or any; default: any
	'numberposts' => -1,    // number of child posts to retrieve; default: -1 (unlimited)
	'post_status' => 'any', // post status: publish, draft, inherit, or any; default: any
);

For (cough) complete information (cough), refer to the official documentation.

Using this functionality, we are well-equipped to use any of the previously discussed template tags (or any other attachment-related tag) to display all of the attachments for each post in the loop. Here is the basic technique, using the wp_get_attachment_link() template tag:

<?php 
$args = array(
	'order'          => 'ASC',
	'post_type'      => 'attachment',
	'post_parent'    => $post->ID,
	'post_mime_type' => 'image',
	'post_status'    => null,
	'numberposts'    => -1,
);
$attachments = get_posts($args);
if ($attachments) {
	foreach ($attachments as $attachment) {
		echo apply_filters('the_title', $attachment->post_title);
		echo wp_get_attachment_link($attachment->ID, 'thumbnail', false, false);
	}
}
?>

When used within the loop, this code will output the title and thumbnail-size image-link for every attachment of each post within the loop. As is, the image-links point to the URI of the original, full-size attachment file. To get the image-links to point to the attachment page for each image, change the third parameter in the wp_get_attachment_link() tag to true.

Currently, the function will display all attachments for each post. To limit the number of attachments displayed, change the numberposts value from “-1” to whatever number you wish.

Once you get the hang of this basic attachment-display method, you can have some fun experimenting with different output formats by swapping out and/or including additional template tags. For example, instead of displaying a thumbnail link along with the attachment title, you may want to display the URI of the original attachment. To do so, you would simply replace this line:

echo wp_get_attachment_link($attachment->ID, 'thumbnail', false, false);

..with this:

wp_get_attachment_url($attachment->ID)

Now, what about all of the other tags? How to implement and integrate them into a cohesive configuration of image-attachment bliss? There are far too many possible configurations to even begin to cover them all, but I did come up with an effective way of demonstrating the configurational possibilities with a little function I like to call the “Attachment Toolbox”.

Image-attachment enlightenment with the Attachment Toolbox

The idea is simple: learn by example. This function is essentially a “live” demonstration of the various template tags and their generated output. To use this function, create a few posts and attach some images (or other types of attachments) to each of them. Then, place the following code into your theme’s functions.php file:

<?php 
function attachment_toolbox($size = thumbnail) {

	if($images = get_children(array(
		'post_parent'    => get_the_ID(),
		'post_type'      => 'attachment',
		'numberposts'    => -1, // show all
		'post_status'    => null,
		'post_mime_type' => 'image',
	))) {
		foreach($images as $image) {
			$attimg   = wp_get_attachment_image($image->ID,$size);
			$atturl   = wp_get_attachment_url($image->ID);
			$attlink  = get_attachment_link($image->ID);
			$postlink = get_permalink($image->post_parent);
			$atttitle = apply_filters('the_title',$image->post_title);

			echo '<p><strong>wp_get_attachment_image()</strong><br />'.$attimg.'</p>';
			echo '<p><strong>wp_get_attachment_url()</strong><br />'.$atturl.'</p>';
			echo '<p><strong>get_attachment_link()</strong><br />'.$attlink.'</p>';
			echo '<p><strong>get_permalink()</strong><br />'.$postlink.'</p>';
			echo '<p><strong>Title of attachment</strong><br />'.$atttitle.'</p>';
			echo '<p><strong>Image link to attachment page</strong><br /><a href="'.$attlink.'">'.$attimg.'</a></p>';
			echo '<p><strong>Image link to attachment post</strong><br /><a href="'.$postlink.'">'.$attimg.'</a></p>';
			echo '<p><strong>Image link to attachment file</strong><br /><a href="'.$atturl.'">'.$attimg.'</a></p>';
		}
	}
}
?>

Then, in your index.php or single.php (or other non-attachment) loop, call the function with the following tag:

<?php attachment_toolbox('thumbnail'); ?>

Then check the results in your browser. You will see that the code has output a variety of different attachment data, including title, attachment URI, post URI, image URI, image thumbnail, image links, and so on. After examining the output, refer back to the function itself to understand the functionality of each tag. Once you begin to see the correlation between source code and page output, you will be well equipped to transform the function in any way you see fit, or even use it as a guide to create your own custom attachment-display function. It’s all there, just dig in and check it out :)

Check please

That does it for this fun-filled DiW article. We have seen how to display many different types of image-attachment information, including everything from thumbnail links and URL paths to custom-sized images and multiple attachments. This collection of recipes is by no means exhaustive, but it provides plenty of key techniques to help implement and customize your own image-attachment functionality. Working with WordPress’ Media Library can be a convoluted process, to say the least, so any tips and tricks that you happen to know will be greatly appreciated by the incredibly awesome WordPress community.

52 Responses

  1. This is just great. I’ve been using a similar function for some time now but this is more flexible as you get more than just the attached image.

    Thanks!

  2. Hi thanks for useful codes, I want “Display the thumbnail of the first image attachment” code, can you write for this tips.

    • $args = array(
             'post_type' => 'attachment',
             'order' => 'ASC',
             'post_mime_type' => 'image',
             'numberposts' => 1,
             'post_status' => null,
             'post_parent' => $post->ID
             );
      $attachments = get_posts($args);
      if ($attachments) {
             foreach ($attachments as $attachment) {
                    //echo apply_filters('the_title', $attachment->post_title);
                           ?>

                    <a href="">
                    ID, 'thumbnail' );
                    ?></a><?
             }
      }

      • Ignore above please … use this to get a link around the first thumbnail in a post.

        $args = array(
               'post_type' => 'attachment',
               'order' => 'ASC',
               'post_mime_type' => 'image',
               'numberposts' => 1,
               'post_status' => null,
               'post_parent' => $post->ID
               );
        $attachments = get_posts($args);

        if ($attachments) {
               foreach ($attachments as $attachment) {
                      ?>
                      <a href="<?php the_permalink(); ?>">
                      <? echo wp_get_attachment_image( $attachment->ID, 'full' ); ?></a><?
               }
        }

  3. This is one of the finer points that can really make a WordPress site unique. It is always good to have ways to accomplish tasks without plug-ins. Thanks for the recipes. Bookmarked and will be used.

  4. Oh, this will be *used*. I have spent enough time battling attachments in a half-hearted approach to deal with WP’s somewhat weak thumbnail support. Thanks!

  5. I wrote an article about this on my site,.. not quite as explicit as yours. Thanks for filling in the gaps, I’m sure there’s more too!
    Can’t wait for WP2.9, apparently this will all be revamped.

  6. Hey, thanks for the info!

    Is there a way to start the attachment loop at the second attachment?

    For example, I want a large image to precede the post text. I want the thumbnails to follow the text.

    It would be redundant to have the main post image also be the first thumbnail.

    Any help would be appreciated.

  7. I’m finding it impossible to style this function:

    'ASC',
           'post_type' => 'attachment',
           'post_parent' => $post->ID,
           'post_mime_type' => 'image',
           'post_status' => null,
           'numberposts' => -1,
    );

    $attachments = get_posts($args);
    if ($attachments) {
           foreach ($attachments as $attachment) {
                  echo wp_get_attachment_link($attachment->ID, 'thumbnail', false, false);
           }
    }
    ?>

    The function can’t be broken up with or tags, either, else it returns an error. I’ve tried styling the img elements returned, too, and that doesn’t seem to work.

    Thanks again

  8. I meant styling with <ul> and <li> tags

  9. is there a way to dynamically generate custom sized image?
    For example: I have default thumbnail set to 150×150, but for specific posts I want it to be 100×100.

  10. Spent about four hours trying to style this so far so each thumbnail has margin-right: 20px applied to it. Even went into the default functions of WordPress, which is a losing game in the end, as WordPress updates override any tinkering I’ve done to the functions (as in removing <li> items

    If this could be styled without leaving the page where this is invoked, that would make my day:

    'ASC',
           'post_type' => 'attachment',
           'post_parent' => $post->ID,
           'post_mime_type' => 'image',
           'post_status' => null,
           'numberposts' => -1,
    );

    $attachments = get_posts($args);
    if ($attachments) {
           foreach ($attachments as $attachment) {
                  echo wp_get_attachment_link($attachment->ID, 'thumbnail', false, false);
           }
    }
    ?>

  11. Super useful article, Jeff. You’re rad.

    Bookmarked!

  12. Great article Jeff,

    I could have used this several months ago (I ended up hacking an inelegant solution).

    One point however: The wp_get_attachment_image() function doesn’t create an alt tag (or title tag), meaning your page won’t be accessible. Hopefully they’ll do something about that in future.

    • Thanks Stephen,

      I think there may be a workaround for the title tag by doing something like this:

      <img src="<?php echo wp_get_attachment_url($post->ID); ?>" alt="<?php $atttitle = apply_filters('the_title',$image->post_title); ?>" />

      Of course, this requires additional code to produce the $atttitle variable and only works if the image/attachment has been given a title.

  13. Shibi Kannan August 14, 2009

    Very nice topic. Just what I was looking for. I was redirected from Drew Douglas Day17 of wordpress screencast from themeforest blog. This site is amazing. Expecting more such great articles with real world examples.

  14. Wow, your walkthrough is better than the actual wordpress codex. It actually blows it away.

    I am trying to create essentially a Photos page, which will contain links to each gallery (which are going to be sub pages for this “photos page”). Any idea how I would access the images of a subpage? I can’t figure out how to get the id out.

    Thanks in advance.

  15. Alright, figured out my last comment. Had it unclear in my head.

    Now I’m trying to mimic Ma.tt’s site.

    http://ma.tt/2009/05/a-day-on-necker-island/
    Any idea how he queries how many comments there are on the photo?

    • He may be using a plugin, or else there may be a way to rig something up using the attachment.php or image.php files.

      One way to find out: ask him! :)

  16. How to test if a page has attachments?

    I’d like to show a gallery, but only on pages that has got one or more images attached. Could I use some sort if conditional to test this??

  17. Anthony August 17, 2009

    Hi, great post! , thanks.

    I’m looking for a way to add a previous/next attachment link on the attachment.php templet.

    Is it something this wp_get_attachment_link($id_next)

    and then you use a script to to set the variable $id_next to current attachment id + 1

    Hope this make sense.

    Thanks

  18. Take,

    Use the wordpress conditional is_attachment().

    Anthony,
    next_image_link('thumbnail','next')

    Will display what you are looking for. If you remove the “next” it will show a thumbnail. You can replace the “next” with any text you want.

  19. I want to list all my images from the attachment page, when I do one of the examples it onyl prints the image name, not the URL or the file ending.

  20. Still fighting styling the results of:

    'ASC',
           'post_type' => 'attachment',
           'post_parent' => $post->ID,
           'post_mime_type' => 'image',
           'post_status' => null,
           'numberposts' => -1,
    );

    $attachments = get_posts($args);
    if ($attachments) {
           foreach ($attachments as $attachment) {
                  echo wp_get_attachment_link($attachment->ID, 'thumbnail', false, false);
           }
    }
    ?>

    It seems to be impervious to CSS interaction. Even a div align center didn’t work after giving up on space between attachment images.

    Any help is appreciated.

  21. @ Nick Reese, I don’t believe I can check if my page has an attachment by using the is_attachment() conditional.. If so, could you give me an example?

    I’m looking for a solution similar to has_excerpt(), only I don’t want to see if my post/page has an excerpt but if it has an image/file attached..

  22. Sebastian August 24, 2009

    *bookmarked page*

    this is just what I needed.

    Anyone out there who could give a hint on how to apply (if possible) this to a specific category?

    I am looking to display ALL (or option to a specific limit) thumbnails of images used in ALL posts in a specific category.

  23. @Take,

    I use Thesis theme can customize via hooks, so your code may need to be different, but here is what my code looks like.

    if (is_attachment()) { ?>
    <div class="attachment-nav">

    <div class="previous"><?php previous_image_link('thumbnail','previous') ?></div>
    <div class="next"><?php next_image_link('thumbnail','next') ?></div>

    </div>
    <div class="clear"></div>
    <?
    echo wp_get_attachment_image( $post->ID, 'large' );
    }
    }

    This code only runs if the post has an attachment and needs to be inside the loop.

    • Looks like I have one extra } at the end.

      • cheers Nick but what I’m trying to achieve is different. I would like to test if the post or page has an attachment, if so I serve a sidebar with thumbs, if not I like to serve a more ‘general’ sidebar.. that’s why has_attachment(); would be a great conditional.. As it doesn’t exist I’m looking for some sort of hack

        • Take, You could always create a custom loop in the sidebar. The attachment system still needs a ton of work and I am sure the wordpress crew will continue to improve upon it.

          If you want to make a secondary loop you will need to use wp_query() and the is_attachment(). This is the only way I can think of to do what you are trying to. (provided I understand it correctly.)

          Maybe the experts here at digwp.com could help.

        • @Take: Just a shot in the dark here, but couldn’t you test for the presence of the $attachment_id variable:

          <?php if($attachment_id) { /* do stuff */ } ?>

  24. I am trying to add the gallery thumbnails to each attachment page so that my readers don’t have to click the browser’s “back” button to see the gallery.

    Any idea how to do this?

  25. john Turner August 25, 2009

    Awesome post, this is coming in super handy for a project I’m working on.

  26. Having a problem with the attachment page. Here’s the invocation code in single.php:

    <?php
    $args = array(
           'order' => 'ASC',
           'post_type' => 'attachment',
           'post_parent' => $post->ID,
           'post_mime_type' => 'image',
           'post_status' => null,
           'numberposts' => -1,
    );
    $attachments = get_posts($args);
    if ($attachments) {
           foreach ($attachments as $attachment) {
                  echo wp_get_attachment_link($attachment->ID, 'thumbnail', true, false);
           }
    }
    ?>

    Here’s the code in attachment.php to display the image. It’s not final, it’s just for testing purposes (and it’s not working):

    <?php echo wp_get_attachment_image(1, 'full', false); ?>

    Ideas on why an image isn’t being returned?

  27. What should my attachment.php file look like in calling a single image?

    It currently looks like:

    <?php $attachment_link = get_the_attachment_link($post->ID, true, array(515, 800)); // This also populates the iconsize for the next line ?>
    <?php $_post = &get_post($post->ID); $classname = ($_post->iconsize[0] <= 128 ? 'small' : '') . 'attachment'; // This lets us style narrow icons specially ?>

    <?php echo $attachment_link; ?><br />
    <?php the_content('<p class="serif">Read the rest of this entry &raquo;</p>'); ?>

    The problem is, the image in attachment.php is clickable and I don’t want it to be.

    Please help. Thanks.

  28. My test single.php is showing all the attachments of ALL POSTS!! (not only the attachments for that post)
    I used the code as said in “Display all attachments for each post”…so, “each” post doesnt mean “The post you are viewing”? I’m confused.

  29. Do you guys have resources for the theme template file attachment.php?

    I’d like to display the full image, display next and previous links to navigate between attachments, and insert a Back To Post button.

    There’s no other posts on this blog pertaining to it, nothing other than a passing mention in the codex, and no mention in Rockstar WordPress, the premium guide released earlier this year.

    … and no discussion on the internet.

    Frustrating!

  30. Awesome! Just want I needed to know for getting the image attached to the index page!

  31. Amazing post. This helped me figure out something I’ve been pulling my hair out over for days.

    I am creating a gallery that does not show the thumbnails – instead it just includes a link to the first image (by menu order) at the bottom of the post. I figured that it would be easy enough to do, but this tutorial was the only way it would work. Thank you!

  32. Eric Chapman September 25, 2009

    This is incredibly usefull..

    Is there a way to make it return the text of an image’s caption, as set in WordPress’ media library?

  33. how i can attach an image to a specific post without without need inserted to that post…

    Then, i will use above attachment technique to call it… and will more managed..

    it not practical if we must [insert to post] uploaded image to make attachment….

    Any plugin or tricks for this…. to make attachment..???
    TQ in advance…

  34. Squarecandy October 8, 2009

    Fantastic post – thanks for all the info.

    One question that doesn’t seem to be addressed in these comments so far:
    how does this work on WP pages as opposed to posts. I would like to use this technique on a custom page template (page.php etc) – everything here talks about index.php, single.php and others that show posts – not pages.

    Pages do have image attachments and are part of the image gallery – can anyone point me in the right direction?

    Thanks!

  35. Ok, I have a list of images generated by function. How can I offset the first image? The offset parameter doenst work in get_children!

  36. This is a great article, we’re using attachment_toolbox as a jumping off point for a couple of sites – thanks!

    I’ve got one question though. We’re now outputting all gallery images into a list, which we’re then showing in a slider function. All good – means we don’t have to use any shortcodes or insert them into the post.

    Occasionally, however, we might want to insert an image into the regular content and not retrieve it into the slider function. Is it somehow possible to modify the attachment_toolbox so it only retrieves those images which are NOT inserted into the actual post? That way, we could upload images for the slider, but still insert images into the post without them ending up in the slider as well.

    Any thoughts on this would be much appreciated!

  37. How do you link back to the original post page from the attachment page? The standard the_title(); just lists the attachments file name.

    • Try with something like this:

      <?php $permalink = get_permalink($post->post_parent); ?>
      <a href="<?php echo $permalink; ?>">Return to article</a>

  38. Sorry this is jibberish to me, I transferred my posts from blogger to WP and bought a theme but I want to get all my old pictures which are located in the posts to come up as the featured picture. Which of these tips should I be using and how do I implement it?

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry