Adding a portfolio to your website is a great way to show the world what you can do. Your portfolio represents what your business does and is a fantastic way to showcase your work. Adding a portfolio is one thing, but you could also give your users easier access to the specific areas of your work, by making your portfolio filterable. Creating a filterable portfolio in Genesis is actually really easy.

Check out the live demo

Follow the below steps to quickly set up an attractive, functional and filterable portfolio in Genesis. Please note, in order for this to work you will need to have the Genesis framework installed.

1/ Register the portfolio

So the first thing you need to do is register the custom post type and custom taxonomies. Luckily there is a plugin that will do all this leg work for you. If you do not already have it installed, go ahead and install the Portfolio Post Type plugin from the WordPress repository. After installing and activating the plugin, you will see that there is a new Portfolio custom post type in the WordPress dashboard. The plugin also registers 2 custom taxonomies, categories and tags.

2/ Edit the functions file

Add the following to your child theme’s functions.php.

<?php
//* Do NOT include the opening php tag
//* Add Archive Settings option to Portolio CPT
add_post_type_support( ‘portfolio’, ‘genesis-cpt-archives-settings’ );
//* Define custom image size for Portfolio images in Portfolio archive
add_image_size( ‘portfolio-image’, 330, 230, true );
view raw functions.php hosted with ❤ by GitHub

3/ Add jQuery files

In order to make our portfolio filterable, we are going to use a fantastic jQuery plugin called Isotope.

Create a directory in the root of your child theme and download the latest version of Isotope, add the isotope.pkgd.min.js file to the js directory.

Create a file and call it isotopes_init.js and place it inside your child themes js directory. Add the following code to the isotopes_init.js file.

jQuery(function($){
$(window).load(function() {
/*main function*/
function portfolioIsotope() {
var $container = $(‘.portfolio-content’);
$container.isotope({
itemSelector: ‘.portfolio-item’
});
} portfolioIsotope();
/*filter*/
$(‘.filter a’).click(function(){
var selector = $(this).attr(‘data-filter’);
$(‘.portfolio-content’).isotope({ filter: selector });
$(this).parents(‘ul’).find(‘a’).removeClass(‘active’);
$(this).addClass(‘active’);
return false;
});
/*resize*/
var isIE8 = $.browser.msie && +$.browser.version === 8;
if (isIE8) {
document.body.onresize = function () {
portfolioIsotope();
};
} else {
$(window).resize(function () {
portfolioIsotope();
});
}
// Orientation change
window.addEventListener(“orientationchange”, function() {
portfolioIsotope();
});
});
});
view raw isotope_init.js hosted with ❤ by GitHub

4/ Create the filterable portfolio page

Create a file in your theme’s directory and call it archive-portfolio.php. Paste the following code into your new file and save.

<?php
/**
* Portfolio Archive
* Author: James Roberts
*
*/
// Force full width content (optional)
add_filter( ‘genesis_pre_get_option_site_layout’, ‘__genesis_return_full_width_content’ );
//remove standard loop (optional)
remove_action( ‘genesis_loop’, ‘genesis_do_loop’ );
// Add our custom loop
add_action( ‘genesis_loop’, ‘lp_filterable_portfolio’ );
// Enqueue javascript
wp_enqueue_script(‘isotope’, get_stylesheet_directory_uri() . ‘/js/isotope.pkgd.min.js’, array(‘jquery’), ‘1.5.25’, true);
wp_enqueue_script(‘isotope_init’, get_stylesheet_directory_uri() . ‘/js/isotopes_init.js’, array(‘isotope’), ”, true);
/**
* Get Excerpt.
*
* @since 1.0
*
*/
function the_excerpt_max_charlength($charlength) {
$excerpt = get_the_excerpt();
$charlength++;
if ( mb_strlen( $excerpt ) > $charlength ) {
$subex = mb_substr( $excerpt, 0, $charlength – 5 );
$exwords = explode( ‘ ‘, $subex );
$excut = – ( mb_strlen( $exwords[ count( $exwords ) – 1 ] ) );
if ( $excut < 0 ) {
echo mb_substr( $subex, 0, $excut );
} else {
echo $subex;
}
echo ‘[…]’;
} else {
echo $excerpt;
}
}
/**
* Output filterable portfolio items.
*
* @since 1.0
*
*/
function lp_filterable_portfolio( ){
$terms = get_terms( ‘portfolio_category’ );
$count=0;
?>
<div class=”archive-description”>
<?php if( $terms ) { ?>
<ul id=”portfolio-cats” class=”filter clearfix”>
<li><a href=”#” class=”active” data-filter=”*”><span><?php _e(‘All’, ‘lp’); ?></span></a></li>
<?php
foreach( $terms as $term ){
echo “<li><a href=’#’ data-filter=’.$term->slug’><span>$term->name</span></a></li>”;
}
?>
</ul><!– /portfolio-cats –><br/><br/>
<?php } ?>
<?php if( have_posts() ) { ?>
<div id=”portfolio-wrap” class=”clearfix filterable-portfolio”>
<div class=”portfolio-content”>
<?php while( have_posts() ): the_post(); ?>
<?php $count++; ?>
<?php $terms = get_the_terms( get_the_ID(), ‘portfolio_category’ ); ?>
<?php if ( has_post_thumbnail($post->ID) ) { ?>
<article class=”portfolio-item col-<?php echo $count; ?> <?php if( $terms ) foreach ( $terms as $term ) { echo $term->slug .’ ‘; }; ?>”>
<a href=”<?php the_permalink() ?>” rel=”bookmark” title=”<?php the_title_attribute(); ?>”><?php echo genesis_get_image( array( size => ‘portfolio-image’ ) ); ?>
<div class=”portfolio-overlay”>
<h3><?php the_title(); ?></h3>
<p><?php the_excerpt_max_charlength(50);?></p>
</div><!– overlay –></a>
</article>
<?php } ?>
<?php endwhile; ?>
</div><!– /themes-content –>
</div><!– /themes-wrap –>
<?php } ?>
</div>
<?php
}
genesis();

5/ Add CSS

Add the following to your child theme’s style.css file.

/* # Filterable portfolio
—————————————————————————————————- */
.post-type-archive-portfolio .archive-description{
overflow: hidden;
}
ul.filter {
color: #999;
list-style: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
ul.filter li {
float: left;
}
ul.filter li:first-child {
margin-left: 0;
}
ul.filter a {
color: #555;
display: block;
padding: 0.5rem 1rem;
text-decoration: none;
border-bottom: none;
font-size: 1.5rem;
font-weight: 300;
border-top: 4px solid #fff;
}
ul.filter a:hover, ul.filter a.active {
border-top: 4px solid #3d91f0;
}
.filterable-portfolio {
margin-left: -2rem;
margin-left: -20px;
}
.portfolio-item {
float: left;
margin-bottom: 2rem;
margin-bottom: 40px;
margin-left: 2rem;
margin-left: 20px;
position: relative;
width: 23%;
}
.portfolio-item a img {
display: block;
margin-bottom: 0;
}
.portfolio-overlay {
color: #fff;
position: absolute;
width: 100%;
text-align: center;
top: 0px;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
padding: 30px;
opacity: 0;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.portfolio-item img:hover + .portfolio-overlay, .portfolio-overlay:hover {
opacity: 1;
}
.portfolio-overlay h3 {
font-weight: bold;
margin: 0;
width: 100%;
padding: 5px 7px;
text-transform: uppercase;
color: #fff;
}
.clearfix{
clear: both;
}
/*———————————————————————————–*
/* = Isotope CSS Animations
/*———————————————————————————–*/
.isotope, .isotope .isotope-item { -webkit-transition-duration: 0.6s; -moz-transition-duration: 0.6s; -ms-transition-duration: 0.6s; -o-transition-duration: 0.6s; transition-duration: 0.6s; }
.isotope { -webkit-transition-property: height, width; -moz-transition-property: height, width; -ms-transition-property: height, width; -o-transition-property: height, width; transition-property: height, width; }
.isotope .isotope-item { -webkit-transition-property: -webkit-transform, opacity; -moz-transition-property: -moz-transform, opacity; -ms-transition-property: -ms-transform, opacity; -o-transition-property: top, left, opacity; transition-property: transform, opacity; }
/**** disabling Isotope CSS3 transitions ****/
.isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition { -webkit-transition-duration: 0s; -moz-transition-duration: 0s; -ms-transition-duration: 0s; -o-transition-duration: 0s; transition-duration: 0s; }
.filterable-portfolio-page .content .entry-header {
margin-bottom: 1rem;
margin-bottom: 10px;
}
.filterable-portfolio-page .content .entry-title {
margin-bottom: 3rem;
margin-bottom: 30px;
}
@media only screen and (max-width: 1179px) {
.portfolio-item {
width: 22%;
}
}
@media only screen and (max-width: 1023px) {
.portfolio-item {
width: 30%;
}
}
@media only screen and (max-width: 500px) {
.portfolio-item {
width: 100%;
}
}
view raw style.css hosted with ❤ by GitHub

6/ Create Portfolio Items

Now all you need to do is add some portfolio items. To add portfolio items, go to Portfolio -> Add New Item in the WordPress dashboard. Now just add a portfolio item as you would a normal post or page, adding a heading, content and a featured image.

Filterable Portfolio

Conclusion

Adding a filterable portfolio in Genesis powered websites is really easy, and takes no time at all. If you wish to change the look of the filterable portfolio page, simple modify the CSS provided in step 5.

I would like to thank a few people whose blog posts and resources have helped me to create this tutorial…

I hope you have found this tutorial useful, if so please feel free to sign up below for regular free content, from WordPress tutorials through to general Genesis tips and tricks.

25 responses to “Filterable portfolio in Genesis”

  1. Christy Avatar

    Hi James! I just used this tutorial and love how easy it was! I’m having one problem though – how do I get the actual portfolio to show up?

    It’s probably super simple and I’m just up too late to figure it out. In the past I’ve created a new page and selected Portfolio under the template, but I don’t see that option. Maybe I missed a step?

    1. James Avatar
      James

      Hi Christy, thanks for reading! This tutorial creates an archive page for your portfolio, so if you go to http://yoururl.com/portfolio/ you should see it working. To edit the archive settings, you can go to Portfolio -> Archive Settings.

      1. Christy Avatar

        Thanks for your speedy reply. I had a few clarification questions and sent a message. 🙂

  2. Sergio Avatar
    Sergio

    Hi. I am trying to use your code but i have a problem. The portfolio page works but the filterable links don´t work.

    I think i have a mistake in tje root ot de isotope code. I dont understand well the ubication of this archives.

    Thank you.

    1. James Avatar
      James

      Hi Sergio, thanks for reading. Can you give me a URL so I can take a look? It sounds to me like the isotope script is not getting enqueued properly.

  3. Kenny Avatar

    There seems to be a bit missing from the foot of the function.php code to get the portfolio gallery working, works fine after adding this.

    /**
     * Template Redirect
     * Use archive-portfolio.php for portfolio category and tag taxonomy archives.
     */
    add_filter( ‘template_include’, ‘sk_template_redirect’ );
    function sk_template_redirect( $template ) {
    if ( is_tax( ‘portfolio_category’ ) || is_tax( ‘portfolio_tag’ ) )
    $template = get_query_template( ‘archive-portfolio’ );
    return $template;
    }

    1. James Avatar
      James

      Hi Kenny, thanks for reading. Looks like that code will just make WordPress use the template we have created if viewing a portfolio category or tag archive, which I can’t see working in this filterable scenario. Would it be possible to explain how the snippet you provided helped? Thanks.

  4. Dallin Avatar

    Great article James, thanks for sharing!

    1. James Avatar
      James

      No problem Dallin, I’m happy you found it useful.

  5. Ollie Avatar
    Ollie

    This is excellent, just exactly what I needed… Thank you.

    Also, how would one go about having the portfolio featured images display above the title on the single portfolio pages?

    thanks in advance 🙂

  6. Nick Avatar
    Nick

    Hi James,

    Many thanks for an awesome portfolio – just one issue I have with it – for some reason mine will only display 10 posts at any one time, even though the ‘post_per_page’ => 9999?

    Any ideas what might also be interfering with this? Thanks in advance, Nick

    1. James Avatar
      James

      Hi Nick, you will most likely need to look at using pre_get_posts https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts. Using this, you will be able to override the number of posts fetched back.

      In my tutorial, the $loop var was not needed, so I have removed it.

  7. Eva Avatar
    Eva

    Hi James,
    Thank you so much for this post. It really works nice and is very easy work with. Just one question… Would it be possible to add some text on the portfolio page, above the portfolio? If so, where should I do that?
    Thank you very much,
    Eva

    1. James Avatar
      James

      Hi Eva,
      Thanks, I’m glad you found the tutorial useful. Re your question, as this is a CPT archive, you should be able to add some text to the CPT archive settings. Note: you may need to register this settings page in your functions.php file. This is a handy article explaining https://carriedils.com/genesis-2-0-archive-settings-custom-post-types/.

  8. Brian Avatar
    Brian

    Hi James,

    I am using the Executive Pro theme and when applying your tutorial I am unable to see the filtered categories across the top.

    There is already a archive-portfolio.php file with this theme.

    In that file I changed the ‘portfolio_category’ term to ‘portfolio_type’ to match that in the functions file that came with the theme.

    Thoughts?

    Thanks,
    Brian

    1. James Avatar
      James

      Hi Brian,

      Do you have a URL you are able to give me so I can take a look?

      Thanks,
      James.

      1. Brian Avatar
        Brian

        Hi James,

        This is a dev site that is not public yet.

        Can I create and email you a login?

        thanks,
        Brian

        1. Brian Avatar
          Brian

          I was able to resolve it.

          Thanks James.

          1. James Avatar
            James

            Hi Brian, that’s great. Out of interest, what was the issue?

  9. Jamie Mitchell Design Avatar

    Hi James!

    Thanks for the great tut, works really well

    Would you have any idea on how to add a lightbox effect? So when the thumbnail is clicked it could say open a video instead of going to the single CPT post.

    the video could be added in the content when creating a post, or even use a custom field, which will be on the archive page, but set to display: none

    then when the thumbnail is clicked, some jquery sets that particular video div to display:block and some css or lightbox takes care of displaying it.

    any ideas appriecated

    1. James Avatar
      James

      Hi Jamie.

      Sure, this is achievable. Personally, I would approach this by using Advanced Custom Fields https://www.advancedcustomfields.com/ to create a custom field, expecting a video URL or YouTube video ID on the edit project page. You could also hide the main content editor if you like. I would then look at implementing a jQuery plugin on the front-end called Pretty Photo http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/, although there are other lightbox plugins that could be used. It would then just be a case of using the lightbox’s js functions to open the lightbox on click, and fill the content with perhaps an embedded YouTube video iFrame by pulling the data from the custom field.

      Thanks,
      James.

  10. Brian Avatar
    Brian

    I am using a term of ‘portfolio-type’ not ‘portfolio_categories’. There are few spots in the archive-portfolio.php file where I had to change out the ‘portfolio-type’.

    Also in this instruction: “Create a directory in the root of your child theme and download the latest version of Isotope, add the isotope.pkgd.min.js file to the js directory.”

    I did not need a directory in my child theme. I just needed to add the .js file to my child theme .js folder.

    How do I control the number of portfolio items to display? The total for my site settings is 9. When I select the second category listed it only gives me the balance of items to equal nine. I would like a total of 6 no matter what the filtered category is.

    Example: If category 1 is 6 items and category 2 is 6 items, when I select category 2 it will only display 3 items to total 9. (6 from cat 1 and 3 from cat 2)

  11. Mike Avatar
    Mike

    How can i make 4 elements in a row?

    1. James Avatar
      James

      There should be 4 items in a row, you can change this by modifying the CSS with of each column.

      1. Eva Avatar
        Eva

        Hi, I have the same problem… I tried to change it, but I keep getting 3 items in a row instead of 4. Sorry for asking, but could you please show where in the CSS the columns should be changed?
        Thanks in advance!

Leave a Reply

You have to agree to the comment policy.