Working with WordPress Post Formats

The WordPress Post Formats feature, introduced in WordPress Version 3.1, allows you to customize the style and presentation of posts. As of this writing, there are 9 standardized Post Formats that users can choose from:

  1. aside
  2. gallery
  3. link
  4. image
  5. quote
  6. status
  7. video
  8. audio and
  9. chat

In addition to these, the default “Standard” Post Format indicates that no Post Format is specified for the particular post.

Add theme support

To add this functionality to your theme, include the following code in your functions.php, specifying the Post Formats you’ll be taking advantage of. e.g. If you only want the aside, image, link, quote, and status Post Formats, your code should look like this:

add_theme_support( 'post-formats', array( 'aside', 'image', 'link', 'quote', 'status' ) );

With that in place, any post written that better fits the mould of an aside, quote, etc can be formatted/identified as such. At this point, the admin Post UI will now have the requisite post formats available to choose from.

Using the post formats

As with most WordPress functions, once you define it in functions.php and have access to it, you then must make use of it in the “front-facing” templates. We just defined 5 of the possible 9 post formats (and we DO intend to use them). This is simple, now all we have to do is run conditional statements to determine what format a certain post is.

If, for instance, we want to do “something special” whenever we have an aside post format, we’d do something like this:

if ( has_post_format( 'aside' )) {
  echo 'do something special';
}

While the above approach works just fine, it’s a rather manual solution. One that will lead to rather bloated code. In your loop, you’d just do the checks needed to establish what post format was being displayed.

However, if you end up implementing several post formats you’ll end up with an ugly if/else conditional soup to this effect:

if ( has_post_format( 'aside' )) {
  // do something for asides
} elseif ( has_post_format( 'image' )) {
  // something for images
} elseif ( has_post_format( 'video' )) {
  // etc, etc
}
 // etc, etc

The above is not a very pragmatic approach. Also a bit unsightly to leave in the views. Luckily, WordPress makes it easy for us to tackle this.

Divide & Conquer

Lets say that you have a standard index.php within which you have a standard loop.

Something like this:

<div class="main-content">
<?php
  if ( have_posts() ) :
    while ( have_posts() ) : the_post();
      // the is where you output your post
      // thumbnail, title, content, etc, etc,
    endwhile;
    else :
      // this is where you output the error message
      // if nothing is found
  endif;
  ?>
</div>

This outputs your posts just fine but now you’ve added support for Post Formats and need to differentiate things a bit visually.

Having defined 5 post formats (‘aside’, ‘image’, ‘link’, ‘quote’, ‘status’ ) earlier, you’ll need to split the loop into 5 distinct post formats to get more granular control of them and in the process DRY up the index.php code.

The first step in splitting our one loop is to establish an intuitive file-naming convention. This way, we can take advantage of the WordPress-provided get_post_format() function.

Template Parts aka Content is king

A nice, intuitive approach is to consider everything within the loop to be “content”. Be it a page, a post (with or without a post format specified), or even a custom post type entry; anything that’s output inside the loop is treated as content.

To that end, we need to split our loop into the 5 specified post formats and an additional ‘default’ format. To do so, we create 6 files and save them in our theme directory:

  1. content-aside.php
  2. content-image.php
  3. content-link.php
  4. content-quote.php
  5. content-status.php
  6. content.php

To start, we copy/paste the ‘content’ part of our loop into each of these files (and edit, style and adjust positioning, etc as we see fit). e.g. the content-link.php should probably not contain an excerpt and should link the the_title() to the relevant URL.

Back in our index.php, where we cut out the loop’s content, we include the following:

get_template_part( 'content', get_post_format() );

So that our loop would now look like this:

<div class="main-content">
<?php
  if ( have_posts() ) :
    while ( have_posts() ) : the_post();
      get_template_part( 'content', get_post_format() );
    endwhile;
  else :
    // this is where you output the error message
    // if nothing is found
  endif;
  ?>
</div>

With this in place, WordPress will now look for a file matching the content-{post_format}.php format and include/output its content here.

While we’re at it, we should also make the same change to the ‘no post(s)’ found part of the loop.

First, create a content-none.php and save it, as you did with the others, in the theme directory. Add the relevant ‘no content found’ message inside that file.

Back in the index, include the below in-between the else: and endif; so that WordPress will know what to output in case we land on a page that has no content.

<div class="main-content">
<?php
  if ( have_posts() ) :
    while ( have_posts() ) : the_post();
      get_template_part( 'content', get_post_format() );
    endwhile;
  else :
    get_template_part( 'content', 'none' );
  endif;
  ?>
</div>

Now whenever WordPress runs through the loop it’ll output our posts, treating and styling them as we defined and when no post is found, our content-none.php file and its content will be displayed.