Template Hijacking and Useful Styling Tricks

Portfolio Press has always used custom post types to display portfolio content. When the theme was released in 2010 this was a novel way to do it (custom post types had just been released in WordPress 3.0).

Post types allowed the portfolio to be styled differently, use different templates, and keep portfolio content separate from standard content. In the dark ages before WordPress 3.0, developers had only achieved this by requiring users to post in a pre-defined category or tag.

screenshot

But since WordPress 3.4 we’ve had post formats like “gallery” and “image” which are now supported by most new themes. With the latest version of Portfolio Press, I wanted users to be able to choose which to use. Post formats are the new default, but users can install the Portfolio Post Type plugin and use post types instead if they choose.

To save a lot of duplication in template code and styling, I used a bit of template hijacking and a few other useful styling tricks. I doubt anyone is working on this exact same issue, but I think some of the ideas might be useful for other applications.

Reusing Template Files

These are all the views that require “portfolio” styling:

is_post_type_archive( 'portfolio' )
is_page_template( 'templates/portfolio.php' )
is_page_template( 'templates/full-width-portfolio.php' )
is_page_template( 'templates/post-format-gallery-image.php' )
is_tax( 'post_format', 'post-format-image' )
is_tax( 'post_format', 'post-format-gallery' )
is_tax( 'portfolio_category' )
is_tax( 'portfolio_tag' )

Since they are all essentially archive views it makes sense to have them use the same template- but by default they will look for different ones. (Read more about template hierarchy in WordPress.)

is_post_type_archive( 'portfolio' ) -> archive-portfolio.php
is_tax( 'post_format', 'post-format-image' ) -> taxonomy-post_format-image.php
is_tax( 'post_format', 'post-format-gallery' ) -> taxonomy-post_format-gallery.php
is_tax( 'portfolio_category' ) -> taxonomy-portfolio_category.php
is_tax( 'portfolio_tag' ) -> taxonomy-portfolio_tag.php

To avoid having to create separate template files, I used template_include filter (thanks to Bill Erickson for the original idea). This is the template hijacking I referred to, and it works like this:

function portfoliopress_template_chooser( $template ) {
	if ( is_tax( 'portfolio_tag' ) ||  is_tax( 'portfolio_category' ) )
		$template = get_query_template( 'archive-portfolio' );
	if ( is_tax( 'post_format', 'post-format-image' ) || is_tax( 'post_format', 'post-format-gallery' ) )
		$template = get_query_template( 'archive-portfolio' );
	return $template;
}
add_filter( 'template_include', 'portfoliopress_template_chooser' );

Now all the taxonomies pull from the same archive-portfolio.php file.

Common Body Classes

The portfolio view requires it’s own unique styling. This is difficult since page templates are being used in some places and archive-portfolio.php in others. The easiest way I found was to apply a common body class ‘portfolio-view’ using the body_class filter:

function portfoliopress_body_class( $classes ) {

	if (
		is_post_type_archive( 'portfolio' ) ||
		is_page_template( 'templates/portfolio.php' ) ||
		is_page_template( 'templates/full-width-portfolio.php' ) ||
		is_page_template( 'templates/post-format-gallery-image.php' ) ||
		is_tax( 'post_format', 'post-format-image' ) ||
		is_tax( 'post_format', 'post-format-gallery' ) ||
		is_tax( 'portfolio_category' ) ||
		is_tax( 'portfolio_tag' )
	) {
		$classes[] = 'portfolio-view';
	}

	return $classes;
}
add_filter( 'body_class','portfoliopress_body_class' );

Changing the Query

One final issue is that each portfolio view needed to display just 9 items. The images are displayed in 3 columns, so if the default 10 were displayed there would always be one hanging at the bottom.

To alter the query on all these templates, I used the pre_get_posts filter. Here’s how it works:

function portfoliopress_portfolio_posts( $query ) {

	if (
		is_post_type_archive( 'portfolio' ) ||
		is_page_template( 'templates/portfolio.php' ) ||
		is_page_template( 'templates/full-width-portfolio.php' ) ||
		is_page_template( 'templates/post-format-gallery-image.php' ) ||
		is_tax( 'post_format', 'post-format-image' ) ||
		is_tax( 'post_format', 'post-format-gallery' ) ||
		is_tax( 'portfolio_category' ) ||
		is_tax( 'portfolio_tag' )
	) {
		$posts_per_page = apply_filters( 'portfoliopress_posts_per_page', of_get_option('portfolio_num','9') );
		$query->set( 'posts_per_page', $posts_per_page );
	}

}
add_action( 'pre_get_posts', 'portfoliopress_portfolio_posts' );

Conclusions

Reusing templates and styling can be a bit tricky to think through- but it can save a ton of code duplication. If you want to see how all this works in a theme, check out Portfolio Press on GitHub.

About Devin

I am a developer based in Austin, Texas. I run a little theme shop called DevPress and help manage a WooCommerce shop with Universal Yums. Find me on twitter @devinsays.

1 Response

Leave a Reply