post: Modular Post-format Templates in WordPress

Home

Case Study: Using post-formats to build modular templates.

Working With WordPress

  

Articles

Bootstrap Templates WordPress

Post-formats were introduced in WordPress 3.1 as a way of adding flexibility into post content display. The issue that most people seem to have, myself included, is their lack of flexibility which particularly dents their usefulness.

In comparison custom post-types & taxonomy functionality, which can be used to build pretty much anything – from image galleries, to fully-functional e-commerce suites, to event calendars have enhanced WordPress immeasurably. Post-formats however are restricted to a number of set types, some of which seem, well not much use.

Post Formats vs. Custom Post Types

So what is the difference between a post-format and a post-type? Post formats allow you to select how the content is displayed, without modifying the content itself. So even with the different presentation styles they are all in the same post-type: post. This is an advantage for the archive page where the available post categories can be used as the post filter. They’ll also show in the same feed and read as the same kind of content.

Custom post types on the other hand are more suitable for specific types of content. They are used to store content not necessarily read by the user as a post, for example a portfolio, event listing, or e-commerce product. They are archived separately and often displayed in a unique format.

Essentially post-formats are a form of taxonomy; post-types are a form of content

Post-Format Types and Set Up

WordPress defines 10 different post-formats:

  • Standard – Regular posts with default formatting
  • Aside – Short content often without the title
  • Gallery – A list of grouped images
  • Link – A link or links and a description
  • Image – Display a primary image
  • Quote – A quotation or testimonial
  • Status – Mini content e.g. Twitter-like message
  • Video – Embedding a video
  • Audio – Embedding audio content
  • Chat – Chat transcript

By default all regular posts start as the ‘standard’ format. They are also not active by default. To enable post-formats you’ll have to add a bit of code to your theme’s functions.php file. Just activate the ones you need. For example:


add_theme_support('post-formats', array( 'aside', 'gallery','link','image','video') );

So, what to do…

When I was looking at building a range of WordPress themes based on bootstrap 3 one thing that stood out was the bootstrap modular component and grid-based system each using a defined section based on the html5 section tag.

Many of the bootstrap css & javascript components can also be readily plugged into the post content via shortcodes. The excellent bootstrap-3-shortcodes plugin is more than sufficient for this. A few custom shortcodes can be written if required to extend the plugin.

Most of the uses of post-formats I have seen described in other articles are in formatting the actual post content. In this case I wanted to leave that alone. Instead I wanted to use the post-formats to build modular post-format templates, essentially bolting-on modules based on the post-format type. Most of the modules would be driven by custom post-meta data selectively added into the post via customized metaboxes.

The restrictions of post-format types is somewhat frustrating. Not being able to create custom formats is a limitation. I can see the WordPress argument that to allow custom post-formats would affect the ability of the site to be moved to a new theme; the posts would then not display properly if the post-format was theme specific. That being said it working with the pre-defined types is relatively sufficient e.g. aside, gallery, image, quote, video.

The two most common methods to add content based on a post-format are using if-else and has_post_format(), or by using the get_post_format(), both in conjunction with the get_template_part() function.


<?php
if ( has_post_format( 'aside' ) ) {
    get_template_part( 'loop', 'aside' );
} else if ( has_post_format( 'gallery' ) ) {
    get_template_part( 'loop', 'gallery' );
} else if ( has_post_format( 'video' ) ) {
    get_template_part( 'loop', 'video' );
} else if ( has_post_format( 'image' ) ) {
    get_template_part( 'loop', 'image' );
} else if( has_post_format( 'gallery' ) ) {
    get_template_part( 'loop', 'gallery' );
}else {
    get_template_part('loop', 'standard');
}
?>

or more simply using WP functions:

<?php get_template_part( 'content', get_post_format() ); ?>

As mentioned, for this case study I’m investigating the use of post-formats to add modular data based on the format and not touching the actual post-content. I prefer to keep all my non-core theme files in separate sub-folders. So in this case within a templates folder. As the extra functionality will be modular I’ve created each post-format type as module-xxx.php e.g. module-image.php & module-video.php. So the code added to the template is as below, including a check that a post-format has been set. If not set then the function returns false – WordPress sets the post-format as ‘standard’ by default.


<?php  if ( has_post_format() ) : get_template_part( 'templates/module', get_post_format() ); endif; ?>

Of course that will be suitable for inserting the module at the same point irrespective of the non-standard post format. To add the module at a specific point for a particular format, for example ‘video’ then use:


<?php  if ( has_post_format('video') ) : get_template_part( 'templates/module', 'video' ); endif; ?>

So for example using the single.php file for generating the regular post output this could be:


<?php
/**
 * Template for displaying Single Post pages. 
 *
 * @package WordPress
 */
?>
<?php get_header(); ?>
    <main role="main" id="wrapper" class="page-content">
    <?php if (have_posts()): the_post(); ?>
        <?php $post_format = get_post_format(); ?>

        <?php  get_template_part( 'templates/post', 'header' ); ?>

        <?php  if ( $post_format == 'image' ) : get_template_part( 'templates/module', 'image' ); endif; ?>

        <?php  if ( $post_format == 'gallery' ) : get_template_part( 'templates/module', 'gallery' ); endif; ?>

        <?php get_template_part( 'templates/post', 'content' ); ?>

        <?php if ( $post_format == 'quote' ) : get_template_part( 'templates/module', 'quote' ); endif; ?>

        <?php if ( empty( $post_format ) ) : get_template_part( 'templates/module', 'featured-image' ); endif; ?>
        <?php if ( $post_format == 'video' ) : get_template_part( 'templates/module', 'video' ); endif; ?>

        <?php get_template_part( 'templates/module', 'comments' ); ?>
    <?php else: ?>

        <?php get_template_part( 'templates/post', 'none' ); ?>
    <?php endif; ?>
<?php get_footer(); ?>

For the additional post-meta data – in this case image, gallery, quote, video – I’m using my own WPR-CPT plugin with which you can quickly add a range of custom post-meta types to a post/page or custom post-type. There are other alternatives out there such as the ACF plugin. So, we can set post-meta for an image and then display in a modular template such as:


<?php
/**
 * Template for displaying the full width header image for blog posts
 *
 * @package WordPress
 */
?>

<?php

// Retrieve header image
$post_image_id  = get_post_meta(get_the_ID(), '_post_image', true);
$post_image     = wp_get_attachment_image_src( $post_image_id, 'full' )[0];

// Display if post image set
if ( !empty( $post_image ) ) : ?>
<section class="container-fluid module">
    <div class="row">
        <div class="col-xs-12 element-img postfade" style="background-image: url('<?php echo $post_image; ?>');"></div>
    </div>
</section>
<?php endif; ?>

Extending Post-Format Templates

So, now we have the ability to create a display according to post-format type. What if we want to create a range of display types for a single post-format, e.g. image? We can do that with the addition of a post_format_type post-meta value. With that we can then define and display a unique post-format template.


<?php
/**
 * Template for displaying Single Post pages. 
 *
 * @package WordPress
 */
?>

<?php get_header(); ?>

    <main role="main" id="wrapper" class="page-content">
    <?php if (have_posts()): the_post(); ?>

        <?php get_template_part( 'templates/post', 'header' ); ?>
        <?php // Retrieve current post-format
            $post_format = get_post_format(); 
            if ( false === $post_format ) { $post_format = 'standard'; }
         ?>
        <?php // Retrieve current post-format type
            $has_meta = metadata_exists( 'post', get_the_ID(), '_post_format_type' );
            $post_format_type = ( $has_meta ) ? get_post_meta(get_the_ID(), '_post_format_type', true) : 'main'; 
        ?>
        <?php get_template_part( 'templates/format', $post_format . '-' . $post_format_type ); ?>

        <?php get_template_part( 'templates/module', 'comments' ); ?>
    <?php else: ?>

        <?php get_template_part( 'templates/post', 'none' ); ?>
    <?php endif; ?>
<?php get_footer(); ?>


<?php
/**
 * Template for the image-main post-format
 *
 * @package WordPress
 * @subpackage Innovate
 */
?>

<?php get_template_part( 'templates/module', 'image' ); ?>

<?php  get_template_part( 'templates/post', 'main' ); ?>

<?php get_template_part( 'templates/post', 'content' ); ?>

<?php get_template_part( 'templates/module', 'featured-image' ); ?>

Some post-format template examples:

In theory the number of template options is unlimited, and as all the templates are based on the same post content and ‘post’ post-type the posts will display the content in the same way and appear in the post archives.

So, there you have an unorthodox method of using post-formats. I hope that gives you an insight into some of the unused flexibility built into WordPress

comments powered by Disqus