Last week I published article How To Add Blueprint Page to Your Genesis Theme and in this article we'll create similar custom post type but with more advanced features like custom taxonomy and filterable archives. In this example we'll create resources page for any Genesis Framework child theme, but you can simply adjust files for other pages (members, portfolio, etc.)
I'd like also say thank you to Pat Fortino, Jennifer Baumann, and Sridhar Katakam as their articles helped me a lot with this tutorial.
This tutorial if for Genesis Framework users only, so grab your copy.
Get Genesis Framework
Required steps
I will explain each of the following steps in detail:
- Add the resources code to your Genesis child theme functions.php
- Add jquery.isotope.min.js and isotope_init.js into js folder.
- In your Genesis child theme folder, create a file called archive-resources.php and single-resources.php
- Add resources css rules into to your Genesis child theme style.css
You can download all required files using this fancy field below.
[sociallocker]
[/sociallocker]
Register Custom Post Type
Similar to previous tutorial we need to register custom post type for resources. Simply paste this code into your Genesis child's theme functions.php file:
/* ----------------------- RESOURCES CODE --------------------------- */
/** Creates resources featured image for archive grid */
add_image_size( 'resources', 330, 230, TRUE );
/** Create portfolio custom post type */
add_action( 'init', 'resources_post_type' );
function resources_post_type() {
register_post_type( 'resources',
array(
'labels' => array(
'name' => __( 'Resources' ),
'singular_name' => __( 'Resources' ),
),
'exclude_from_search' => true,
'has_archive' => true,
'hierarchical' => true,
'taxonomies' => array( 'resources-type' ),
'public' => true,
'rewrite' => array( 'slug' => 'resources' ),
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'revisions', 'page-attributes', 'genesis-seo', 'genesis-cpt-archives-settings' ),
)
);
}
/* Register Resources Taxonomy */
add_action( 'init', 'create_resources_tax' );
function create_resources_tax() {
register_taxonomy(
'resources-type',
'resources',
array(
'label' => __( 'Resources Type' ),
'hierarchical' => true
)
);
}
The first piece of code will create custom post type called 'Resources' and second will create custom taxonomy for this CPT which is required to enable filtering resources by type.
jQuery stuff
Create js folder in child theme's root directory and then download the latest Isotope script, jquery.isotope.min.js from http://isotope.metafizzy.co/ and upload it to js directory. Also upload another file isotope_init.js having filled with this code (props Sridhar Katakam)
jQuery(function($){
$(window).load(function() {
/*main function*/
function wpexresourcesIsotope() {
var $container = $('.resources-content');
$container.imagesLoaded(function(){
$container.isotope({
itemSelector: '.resources-item'
});
});
} wpexresourcesIsotope();
/*filter*/
$('.filter a').click(function(){
var selector = $(this).attr('data-filter');
$('.resources-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 () {
wpexresourcesIsotope();
};
} else {
$(window).resize(function () {
wpexresourcesIsotope();
});
}
// Orientation change
window.addEventListener("orientationchange", function() {
wpexresourcesIsotope();
});
});
});
Custom archive template
In this step you have to create archive-resources.php file in your Genesis child theme root directory.
With default archives template it's pretty simple, but when you want filterable items it's a little bit more tricky. Here's the code for archive-resources.php
<?php
/**
* The custom resources post type archive template for a Filterable resources
*/
# Force full width content
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
wp_enqueue_script('isotope', get_stylesheet_directory_uri() . '/js/jquery.isotope.min.js', array('jquery'), '1.5.25', true);
wp_enqueue_script('isotope_init', get_stylesheet_directory_uri() . '/js/isotope_init.js', array('isotope'), '', true);
//* Add custom body class
add_filter( 'body_class', 'filerable_resources_add_body_class' );
//* Filterable resources custom body class
function filerable_resources_add_body_class( $classes ) {
$classes[] = 'filterable-resources-page';
return $classes;
}
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'filterable_resources_do_loop' );
/**
* Outputs a custom loop
*
* @global mixed $paged current page number if paginated
* @return void
*/
function filterable_resources_do_loop() { ?>
<header id="page-heading">
<?php $terms = get_terms( 'resources-type' ); ?>
<?php if( $terms[0] ) { ?>
<ul id="resources-cats">
<li><a href="#" data-filter="*"><span><?php _e('All', 'genesis'); ?></span></a></li>
<?php foreach ($terms as $term ) : ?>
<li><a href="#" data-filter=".<?php echo $term->slug; ?>"><span><?php echo $term->name; ?></span></a></li>
<?php endforeach; ?>
</ul><!-- /resources-cats -->
<?php } ?>
</header><!-- /page-heading -->
<div itemprop="text">
<?php if( have_posts() ) { ?>
<div id="resources-wrap">
<div>
<?php $wpex_count=0; ?>
<?php while( have_posts() ) : the_post() ?>
<?php $wpex_count++; ?>
<?php $terms = get_the_terms( get_the_ID(), 'resources-type' ); ?>
<?php if ( has_post_thumbnail($post->ID) ) { ?>
<article>
<a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title_attribute(); ?>"><?php echo genesis_get_image( array( size => 'resources' ) ); ?>
<div><h3><?php the_title(); ?></h3></div><!-- resources-overlay --></a>
</article>
<?php } ?>
<?php endwhile; ?>
</div><!-- /resources-content -->
</div><!-- /resources-wrap -->
<?php } ?>
<?php wp_reset_postdata(); ?>
</div><!-- /entry-content -->
<?php }
genesis();
And now you should see quite ugly resources page, create some resources items and assign them with proper types. Here's mine for sake of this tutorial:
Then simply navigate to http://yourdomain.com/resources and it WORKS!
Custom single template
You can skip this step if you don't want custom template, but it's easier to add or remove sections like author box, custom page layout, ads, sidebars etc. Create single-resources.php file in your Genesis child theme and here is the code I'm using:
<?php
/** Remove the post info function */
remove_action( 'genesis_before_post_content', 'genesis_post_info' );
/** uncomment line below if you are using any after post widgets */
/** remove_action( 'genesis_after_post_content', 'genesis_after_post' ); */
/** Remove the author box on single posts */
/** Remove the post meta function */
remove_action( 'genesis_after_post_content', 'genesis_post_meta' );
/** Remove the comments template */
remove_action( 'genesis_after_post', 'genesis_get_comments_template' );
genesis();
CSS Styles
Let's do some styling to make our page more representative. You should modify this code that it'll fit your site designs.
/*
Filterable resources
---------------------------------------------------------------------------------------------------- */
#page-heading {
height: 2rem;
margin-bottom: 2rem;
}
ul.filter {
color: #999;
list-style: none;
margin-left: 0;
}
ul.filter li {
float: left;
margin-left: 1rem;
margin-left: 10px;
margin-bottom: 1rem;
margin-bottom: 10px;
}
ul.filter li:first-child {
margin-left: 0;
}
ul.filter a {
background: #333;
color: #fff;
display: block;
padding: 0.5rem 1rem;
text-decoration: none;
border-bottom: none;
font-size: 1.5rem;
font-weight: 300;
}
ul.filter a:hover, ul.filter a.active {
background: #0ebfe9;
}
.filterable-resources {
margin-left: -2rem;
margin-left: -20px;
overflow: hidden;
}
.resources-item {
float: left;
margin-bottom: 2rem;
margin-bottom: 20px;
margin-left: 2rem;
margin-left: 20px;
position: relative;
width: 270px; /* [main element width - (number of columns - 1)*20]/number of columns */
/*width: 366px; For 3-columns */
}
.resources-item a {
display: block;
border-bottom: none;
}
.resources-item a img {
display: block;
background: none;
padding: 0;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
width: 100%;
margin-bottom: 0;
}
.resources-overlay {
bottom: 0;
left: 0;
position: absolute;
}
.resources-overlay h3 {
background: #000;
color: #fff;
font-size: 1.2rem;
font-weight: normal;
margin: 0;
max-width: 180px;
padding: 5px 7px;
text-transform: uppercase;
}
/*-----------------------------------------------------------------------------------*
/* = 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-resources-page .content .entry-header {
margin-bottom: 1rem;
margin-bottom: 10px;
}
.filterable-resources-page .content .entry-title {
margin-bottom: 3rem;
margin-bottom: 30px;
}
@media only screen and (max-width: 1179px) {
.resources-item {
width: 306px;
}
}
@media only screen and (max-width: 1023px) {
.resources-item {
width: 242px;
}
}
@media only screen and (max-width: 768px) {
.resources-item {
width: 217px;
}
}
@media only screen and (max-width: 320px) {
/* Uncomment the following only if the last filter item is on its own in a separate line like this: http://i.imgur.com/0VD8tmU.png */
ul.filter li:last-child {
margin-left: 0;
}
}
And here you see the final result:
Overview
I hope this tutorial will be useful for you. There are of course other methods of creating custom post types, but I like to code such things myself instead of using plugins. I know what is in the code, simple. There are also cons of this solution - when you change theme all custom post types are gone, but if you are not going to make any changes it's fine. You can also transfer this settings into next template.
If you need help or want to share your ideas let us know in the comments.
Thanks for this tutorial, I've been looking for it for some time.
But I have a problem, on archives-resources.php both css and resources are not displayed ... can you help me out?
Quite simply .... thank you! I have attempted to do the same tutorial by Sridhar Katakam and I just cannot get the filtering to happen - but following your tutorial and having the RESOURCES means that its working and I now have files to reference back over to understand the code and work out why the previous tutorial by Sridhar Katakam wasn't working.
Thank you - nice to see things working.
Just the tutorial i'm looking for. Downloaded the files and integraded it into a child theme. When i go to http://localhost:8888/resources i get a 404, what's going wrong?
Oke this is stupid, offcourse i've to check the permalink settings. It works like a charme, thanks for the great tutorial!
Haha 🙂 I'm glad it helped you!
Hi! Thank you so much for your great tutorial! I decided to give the genesis framework a go since I'm new to theme development and did not have the skills to start totally from scratch. I just wanted to ask you a question. I'm having trouble with displaying the resources by using the archives-resources.php. It seems both the css and the resources them selves are not showing. Do you have any idea what could be the problem there? The categories are displaying, but as a ul list.
Hi!
Contact me via the services page and we'll figure it out together.