File attachments are not new to WordPress — you can attach almost any kind of file to your posts, pages and custom post types. There’s also the Media Manager where you can upload files without attaching them to a certain post or page. Attachments are most commonly used to display images in the post content, but sometimes also used to link to files that are relevant to the post. For example, you might want to attach the complete source code for a tutorial post for readers to download, or an icon set giveaway with a download link to an archive.
WordPress allows to link to attached files from within the post content which is the most common scenario, but today I’ll show you a different approach. In this post I’ll create a child theme based on Twenty Eleven (again) and have it display all the attached files to each post in a nice looking list at the end of the post content. I’ll be using a few simple actions and filters to hook to the post content, as well as attach a stylesheet which will make the list visually appealing by providing different icons for different file types.
Why Child Theme? And Why Twenty Eleven?
I’m afraid I don’t have a good enough reason for this. Child themes are relatively new so practicing this kind of stuff on child themes instead of plugins will give you some good experience, experience you didn’t have with plugins. I also think that any editions to visual side of your website should be done using child themes and let plugins have the rest. Why Twenty Eleven? You might have noticed that I’m obsessed with Twenty Eleven, starting with a Twenty Eleven review and following up by a tutorial on how to add a color scheme to Twenty Eleven.
In this tutorial I’ll be using the same child theme techniques (as in the color scheme tutorial), and in fact, I’ll be using my same old functions.php file and simply adding some more code to that.
Understanding Post Attachments
Behind the scenes, post attachments are very like posts and pages themselves. They’ve got a title, description (or content) and a permalink. In addition post attachments come with a file mime type and an absolute link to the file itself (don’t confuse with permalink). The attachment post parent is set to the post or page to which the file was uploaded, or set to 0 if it wasn’t attached to one. The post status is inherited from the parent post, meaning if the parent post is a draft, the attachment post is considered to be a draft as well. And if it’s published then the attachment post is published too.
Hopefully you’ve got a local WordPress installation running with the Twenty Eleven theme, so go ahead and create a new post with some lorem ipsum text, and attach a few files to that post, of different mime types. In this tutorial I’ll use an image, a word document, a flash file, a PDF file and a zip archive. Give each of the attachments to your post a relevant name, try to describe the contents of the file, while I’ll describe the type of the file for illustration purposes.

After you’ve done that, don’t insert any of the uploaded files in your post. Simply close the file manager dialog box and publish your post. Nothing strange so far, right?
Displaying the Post Attachments
Now comes the fun part, open up that functions.php file of your child theme. We’re going to use a filter called the_content and before returning the post content, we’ll append our attachments list to it. Here’s the code snippet:
add_filter( 'the_content', 'my_the_content_filter' );
function my_the_content_filter( $content ) {
global $post;
if ( is_single() && $post->post_type == 'post' && $post->post_status == 'publish' ) {
$attachments = get_posts( array(
'post_type' => 'attachment',
'posts_per_page' => 0,
'post_parent' => $post->ID
) );
if ( $attachments ) {
$content .= '<h3>Attachments</h3>';
$content .= '<ul class="post-attachments">';
foreach ( $attachments as $attachment ) {
$class = "post-attachment mime-" . sanitize_title( $attachment->post_mime_type );
$title = wp_get_attachment_link( $attachment->ID, false );
$content .= '<li class="' . $class . '">' . $title . '</li>';
}
$content .= '</ul>';
}
}
return $content;
}
It’s pretty easy to understand this. The filter is executed when the Twenty Eleven template files use the function called the_content which, just like it sounds, displays the post contents, so we’re hooking to that. We’re declaring $post as a global variable and that’s where the current post is stored when we’re in the loop. After some checks to make sure we’re acting on a single post which is published, we use the get_posts functions to give us all the attachments (posts per page set to zero means unlimited) that are attached (children of) the current post ID, which is their parent.
Then goes a check to make sure the attachments array is not empty — we don’t want to print the attachments heading if there are no files, right? We’re appending the new stuff to the $content variable which is returned at the end, starting with the attachments heading, the opening unordered list tag and followed by a foreach loop that walks through each attachment and creates a list item.
The $class variable is generated based on the current attachment’s mime type, we’ll use these classes later in CSS to style file types differently. The wp_get_attachment_link returns a hyper link to the attached file. After the foreach loop ends, don’t forget to close the unordered list tag. And as I said, the $content variable is returned at the end, don’t forget that, otherwise you’ll end up with an empty content for each post.
Following the code above, this should generate a simple heading and a list of file attachments for each post that has any. Here’s what my post now looks like:

Adding Icons to the Post Attachments
So far so good, but we’re all used to seeing the icons for every file type in attachment lists, right? So that’s what we’re going to do in this step, with the help of those classes from mime types that we set in the list earlier. So create a new file in your child theme’s directory, call it attachments.css. Use the wp_print_styles action and add your stylesheet using wp_enqueue_style, like this:
add_action( 'wp_print_styles', 'my_enqueue_style' );
function my_enqueue_style() {
wp_enqueue_style( 'post-attachemnts', get_stylesheet_directory_uri() . '/attachments.css', array(), null );
}
Pretty straightforward, right? Now comes the really fun part. Go out there and find a nice looking icon set with file types. You can use ones used in your operating system or you can use the icons that Apache provides. A good place to look for free icons is gnome-look.org but today I’ll be using a great icon set I stumbled across a few days ago — Fugue Icons, a set of over 3000 nice looking icons, including ones for different file types. Licensed under Creative Commons Attribution 3.0, so read carefully before using them in your projects.
So download the icons and place them in your child theme somewhere (I used the icons folder). Fire up your stylesheet and create a few rules for your attachments list. I started by styling the unordered list itself, and then the list items with a “one rule for all”. This is done for fallback, in case there’s no suitable entry for the attachement’s mime type, it will not come without an image.
ul.post-attachments {
list-style: none;
margin-left: 0;
}
li.post-attachment {
background: url(icons/document.png) 0 4px no-repeat;
padding-left: 24px;
}
This gave each of my list entries a nice looking document icon, like this:

Now, use your inspector to figure out the extra class name that’s been given to each of your attachment files, you’ll see that mime types are sanitized there, ready for use in your stylesheets, for example mime-imagejpeg for JPEG images and mime-applicationzip for Zip archives. Here’s how I structured my CSS to display the correct icons for my file types.
.post-attachment.mime-imagejpeg,
.post-attachment.mime-imagepng {
background-image: url(icons/document-image.png);
}
.post-attachment.mime-applicationzip {
background-image: url(icons/document-zipper.png);
}
.post-attachment.mime-applicationpdf {
background-image: url(icons/document-pdf.png);
}
.post-attachment.mime-applicationx-shockwave-flash {
background-image: url(icons/document-flash-movie.png);
}
.post-attachment.mime-applicationmsword {
background-image: url(icons/document-word.png);
}
As you can see, I took JPEG and PNG images, Zip, PDF, SWF and Microsoft Word files. Go ahead and extend the list to all the suitable icons available in your set and don’t worry if you miss one, since there’s always the fallback to the default icon if an entry for the mime type doesn’t exist. Here’s how my new list looks:

Wrapping Up
That’s all folks. Your posts now have sweet looking attachments in them with links to the attachment files and descriptive icons. First question I’d ask myself is how would I remove an attachment from the list without deleting the attachment file. Well this is not about removing but about hiding, since an attached file is an attached file, and if you’re displaying attached files you’re displaying every attached file (did this make sense?).
If you don’t want your files to show up as attachments don’t attach them. But if you want to use them in your post (like images for instance) content, use the Media Library to upload the files without attaching them to posts. This is the simplest solution I can think of ;)
Anyways, hope you’ve learned something new today and tell us how you’re dealing with post attachments. Should you have any questions or suggestions, the comments section below is available. Thanks for being with us and don’t forget that we’re on Facebook too!



Thanks Konstantin – I can see this being very useful.
And thanks also for the Google + invite, much appreciated.
Cheers
Hey Don, you’re very welcome and stay tuned for more ;)
Wow, this is incredibly helpful for me (and coincidentally relevant to a project I’m working on right now). Thanks for putting this post together!
You’re welcome Loren!
This was very helpful for a project I’m working on at the moment.
I’d like to filter out attachments that are already inserted in the post. There’s this, http://wordpress.stackexchange.com/questions/4261/how-can-you-determine-whether-an-image-is-merely-attached-or-has-actually-been-in/19752#19752 — although it would have to be extended to more than just images.
Do you recommend this solution? If not, how would you approach it?
Pauli,
Thanks for your comment. The solution in that stack exchange post is called “hacking”. It might work but there’s no guarantee it will work forever. Off the top of my head I can think of three options. First, you can simply use the media library to upload items and not attach them to a post but use the file URL anywhere you like. That way it will not show up as an attachment. Second option is use the extra fields like title and description, i.e. if a description has been filled out, print the attachment, otherwise don’t. Not too elegant I know but something that can work.
Third (and probably best) would be to use the post meta. You see, attachments are entries in the very same wp_posts table, so wp_postmeta is easily applicable to them, so the standard meta functions will work. The actual implementation might be easy, but it’ll be difficult to somehow insert this into the UI.
Hope this is helpful, cheers!
I see your point.
I think the ideal solution would be to extend one of the plugins that display attachments in the post editor to support an include/exclude toggle, to allow manual exclusion of items from appearing in the automated links section.
Since the same item may be attached to more than one post, I guess the meta content could be something like a pipe separated list of post_ids on which to suppress automated list inclusion.
Pauli, good idea, I’d say comma-separated though, but it still would be difficult for non-geekish users to figure out the post ID of the attachment posts, unless you explicitly display that somewhere :)
I had an ajax toggle in mind, no need for the user to figure out the post_id at all.
Okay AJAX toggles are interesting, good luck with that :) Give us a shout on how it turns out!
Konstantin,
Thanks for this—it’s very helpful. I am using it on my site to display a list of documents attached to posts, but I have been struggling with one thing and I am hoping you’ll have the answer.
My Single Post template displays one large image, and below I am using the standard WP image gallery so that users can rotate through the other images. Below that I am displaying the attached document files separately using the method you suggested.
I wanted my Image.php template to look the same as the Single.php one, and I’ve set it up so that when a user clicks on an image in the gallery, they will see the same content with only the main image swapping out. Problem is I would like the same file attachments to show as well, and because the function refers to the current post’s ID, those icons are not showing up.
Can you suggest some code to refer to the image post’s parent, so that the same list of attached files will show up when viewing an image in my Image template too?
Hope this makes sense and I appreciate your help!
Hey Daniel, glad the article was helpful. I’m not sure you’re taking the right approach but in your case it’s pretty easy to grab the post parent’s ID instead of the current post’s ID when using
get_posts, so instead of$post->IDjust use$post->post_parentin your image.php template, assuming the image’s parent post is the one containing your attached files. Cheers!Much appreciated. I’ve been struggling to understand how attachments were different to post content and this has really helped me out.
I was going to edit my single.php but seeing it done as a filter in functions.php makes it much cleaner.
Thanks!
Glad it worked out for you Richard, thanks for your comment!
Thanks for this post who help me a lot doing my WordPress theme.
I added that and changed it a bit to fit my need with the plugin Attachments.
It works like a charm !
-> Website bookmarked !
You’re welcome Yann, glad it worked out for you :) Thanks for your comment!
Konstantin Kovshenin
You are da man !
Your site is packed with useful WP how to.
Please keep it up.
:)
Hi , I have done it and it does work but i need a counter , i mean i would like to count that media file download and try to make a page where i could show just the top most downloaded post in entire website.I am not using any plugin , i need to do it custom how could i do that .Any idea …Please let me updated …