This tutorial is designed for intermediate developers. It will get you started, but you’ll need to tweak the template files to your own needs.
A few of the StudioPress child themes include a portfolio page, like Modern Portfolio and Jane. But what if you’ve found a theme you want and it doesn’t include this feature?
It’s actually not that difficult to add to any theme. And even if your theme already includes it, this plugin-based approach will ensure your portfolio will keep working when it comes time to change themes.
An Integrated Approach
Just like Event Calendar Integration, this is a feature that should be built using a plugin and your theme.
The plugin contains the functionality: registering a “portfolio” post type, a “portfolio categories” taxonomy, any necessary metaboxes…all of the backend features that should be theme-independent and stay with you when you change themes in the future.
The theme is responsible for styling how the portfolio looks. If you don’t make any changes to your theme, the portfolio will look like another blog (because it will inherit the styling from that section). In the future if you change themes, you’ll want to update the design of that theme with regards to your portfolio.
Set up the backend
Install the Portfolio Post Type plugin. This will add a “Portfolio” post type below your “Posts”.
Add your portfolio items, making sure to add images for each one so the layout looks good in the next step.
If you go to yoursite.com/portfolio, you’ll see all your portfolio items showing up but it looks like a blog – just title and post content.
Styling your Portfolio
Create a theme file called archive-portfolio.php
and place it in your child theme. Place this code in it:
<?php | |
/** | |
* Portfolio Archive | |
* | |
*/ | |
/** | |
* Display as Columns | |
* | |
*/ | |
function be_portfolio_post_class( $classes ) { | |
global $wp_query; | |
if( !$wp_query->is_main_query() ) | |
return $classes; | |
$columns = 3; | |
$column_classes = array( '', '', 'one-half', 'one-third', 'one-fourth', 'one-fifth', 'one-sixth' ); | |
$classes[] = $column_classes[$columns]; | |
if( 0 == $wp_query->current_post % $columns ) | |
$classes[] = 'first'; | |
return $classes; | |
} | |
add_filter( 'post_class', 'be_portfolio_post_class' ); | |
// Remove items from loop | |
remove_action( 'genesis_entry_header', 'genesis_post_info', 12 ); | |
remove_action( 'genesis_entry_content', 'genesis_do_post_content' ); | |
remove_action( 'genesis_entry_footer', 'genesis_entry_footer_markup_open', 5 ); | |
remove_action( 'genesis_entry_footer', 'genesis_post_meta' ); | |
remove_action( 'genesis_entry_footer', 'genesis_entry_footer_markup_close', 15 ); | |
/** | |
* Add Portfolio Image | |
* | |
*/ | |
function be_portfolio_image() { | |
echo wpautop( '<a href="' . get_permalink() . '">' . genesis_get_image( array( 'size' => 'medium' ) ). '</a>' ); | |
} | |
add_action( 'genesis_entry_content', 'be_portfolio_image' ); | |
add_filter( 'genesis_pre_get_option_content_archive_thumbnail', '__return_false' ); | |
// Move Title below Image | |
remove_action( 'genesis_entry_header', 'genesis_entry_header_markup_open', 5 ); | |
remove_action( 'genesis_entry_header', 'genesis_entry_header_markup_close', 15 ); | |
remove_action( 'genesis_entry_header', 'genesis_do_post_title' ); | |
add_action( 'genesis_entry_footer', 'genesis_entry_header_markup_open', 5 ); | |
add_action( 'genesis_entry_footer', 'genesis_entry_header_markup_close', 15 ); | |
add_action( 'genesis_entry_footer', 'genesis_do_post_title' ); | |
genesis(); |
The first secton of code is breaking the portfolio into columns. Change the
$columns = 3
to however many columns you want (2-6). If your portfolio is not showing up in multiple columns, your theme might be missing the Column Classes CSS. Go to that link and copy/paste the CSS to your style.css
file.
The second section is removing items we don’t want showing up in the loop. I’m removing the post info (date and author at top), post content, and post meta (categories at bottom). I’m also removing the markup for the entry’s footer since we no longer have a footer.
The third section is adding an image to replace the post content. I’m using the medium image size, which you can manage in Settings > Media. You might also consider creating your own image size in functions.php
.
The fourth section moves the post title below the featured image.
With that in place, you should have a pretty good portfolio set up. You might want to do some additional styling or changes to the template file, but now you have a starting point. Here’s what it looks like on my demo site:
Use same template for taxonomies
The plugin includes Portfolio Categories and Portfolio Tags taxonomies. You could duplicate the template file into taxonomy-portfolio_category.php
and taxonomy-portfolio_tag.php
, but that means if you make changes in the future you’ll need to update 3 files.
A cleaner approach is to put this in functions.php
:
<?php | |
/** | |
* Portfolio Template for Taxonomies | |
* | |
*/ | |
function be_portfolio_template( $template ) { | |
if( is_tax( array( 'portfolio_category', 'portfolio_tag' ) ) ) | |
$template = get_query_template( 'archive-portfolio' ); | |
return $template; | |
} | |
add_filter( 'template_include', 'be_portfolio_template' ); |
That tells WordPress “if we’re on either the portfolio category or portfolio tag taxonomies, use the portfolio archive template file”.
Ordering projects
Right now the projects are showing up in reverse chronological order – the most recently published are at the top. But since this is a portfolio, you might want to put your most impressive projects at the top, regardless of post date.
Add this to your functions.php
file:
<?php | |
/** | |
* Add 'page-attributes' to Portfolio Post Type | |
* | |
* @param array $args, arguments passed to register_post_type | |
* @return array $args | |
*/ | |
function be_portfolio_post_type_args( $args ) { | |
$args['supports'][] = 'page-attributes'; | |
return $args; | |
} | |
add_filter( 'portfolioposttype_args', 'be_portfolio_post_type_args' ); | |
/** | |
* Sort projects by menu order | |
* | |
*/ | |
function be_portfolio_query( $query ) { | |
if( $query->is_main_query() && !is_admin() && ( is_post_type_archive( 'portfolio' ) || is_tax( array( 'portfolio_category', 'portfolio_tag' ) ) ) ) { | |
$query->set( 'orderby', 'menu_order' ); | |
$query->set( 'order', 'ASC' ); | |
} | |
} | |
add_action( 'pre_get_posts', 'be_portfolio_query' ); |
You can now use the “Page Attributes” box in the right column when editing a portfolio item to set the order, or install a plugin like Simple Page Ordering which will let you drag them around from the main portfolio edit screen.
Jamie Mitchell says
Hi Nick
you can easily modify the default loop when using the front-page.php template to show portfolio CPT’s
https://gist.github.com/jamiemitchell/10957259
Nicola says
Hi Bill, thanks from Italy for your amazing tutorials! I was wandering if is possible, inside this query, to isolate the most recent portfolio item and query it, in full width, before the columns!
Thank you!
Daniel says
This post helped me a LOT! I’ve been wracking my brain trying to figure out this weird Genesis way of doing things. My client has Agency Pro running and wants me to create an ensemble page – basically like a portfolio list. Created the CPT and some fields using ACF as I was used to, only to find out that Genesis and its child themes are not coded the way I normally code themes š
Anyhow … here’s my question: can you give me a point to start when I want create an archive that is grouped into categories? So that the output is sort of like
Category title
column item column item column item column item
Category title
column item column item column item column item column item column item
Category title
column item column item
etc.
Much appreciated.
Bharat Go Digital says
This is very useful and works a treat. Iād really like to use this as a page template though.
Joyce Grace says
Hi! Thank you very much for this. I tried it out, and noticed that the archive headline and intro text don’t come into play with the portfolio archive template. Is there an obvious thing I’m missing? Sorry if this is in plain sight!
Bill Erickson says
You need to enable archive settings for the post type.
The example above uses the “Portfolio Post Type” plugin, so you can enable archive settings on it using this: https://gist.github.com/billerickson/684ed9d0ef419f2aad6630a44d8eec6a
Michel says
Interesting I copied the archive-portfolio.php as is, but the strange thing is that the removing of the title is only working for the first post. The other posts now have the title twice. One above and one below the image.
Michel says
What I mean is that this line (line 48 in the example):
remove_action( ‘genesis_entry_header’, ‘genesis_do_post_title’ );
Is only working on the first post and not all entries.