Today, you will change your simple portfolio into something amazing with the magic of Quicksand by Razorjack.
Introduction
Ever wanted to use the jQuery plugin Quicksand? Ever tried to implement it with WordPress? But, found it a nightmare to do both? Well, I will be going through a simple step-by-step guide to get you from a blank WordPress theme to a beautiful custom portfolio with the use of Quicksand. I'll be using a custom theme which has been stripped down for the purpose of this tutorial along with WordPress 3.0+.
So open up your favourite text editor and let's begin!
Step 1 Create a Post Type
With WordPress, we are capable of creating custom post types where we can manage all of our content. We will create a custom post type to store all of our portfolio items in a dedicated admin section.
For easy code management, let's begin by creating a folder called portfolio and a PHP file called portfolio-post-types.php (or anything you find suitable).
Once you have created a file, let's add some code...
Let's start by creating a function:
<?php // function: post_type BEGIN function post_type() { // We will fill this function in the next step } // function: post_type END
Now that we have created our blank function, let's add some code to make this function do something special. First, create the labels for our custom post type. Insert the following piece of code in our post_type function:
$labels = array( 'name' => __( 'Portfolio'), 'singular_name' => __('Portfolio'), 'rewrite' => array( 'slug' => __( 'portfolio' ) ), 'add_new' => _x('Add Item', 'portfolio'), 'edit_item' => __('Edit Portfolio Item'), 'new_item' => __('New Portfolio Item'), 'view_item' => __('View Portfolio'), 'search_items' => __('Search Portfolio'), 'not_found' => __('No Portfolio Items Found'), 'not_found_in_trash' => __('No Portfolio Items Found In Trash'), 'parent_item_colon' => '' );
A breakdown of the code we have just written:
The 'labels' variable is an array of strings that represent your post type, each of the strings are text which is output for the particular function.
-
name
– The plural form of the name of your post type. -
singular_name
– The singular form of the name of your post type. -
rewrite
– Rewrite permalinks with this format. -
add_new
– The menu item for adding a new post. -
edit_item
– The header shown when editing a post. -
new_item
– Shown in the favourites menu in the admin header. -
view_item
– Shown alongside the permalink on the edit post screen. -
search_items
– Button text for the search box on the edit posts screen. -
not_found
– Text to display when no posts are found through search in the admin. -
not_found_in_trash
– Text to display when no posts are in the trash. -
parent_item_colon
– Used as a label for a parent post on the edit posts screen. Only useful for hierarchical post types.
Next, create the arguments for our custom post type. Insert the following piece of code into our post_type function:
$args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'query_var' => true, 'rewrite' => true, 'capability_type' => 'post', 'hierarchical' => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'thumbnail' ) );
-
labels
– An array of labels for this post type. -
public
– Meta argument used to define default values for publicly_queriable, show_ui, show_in_nav_menus and exclude_from_search. -
publicly_queryable
– Whether post type queries can be performed from the front end. -
show_ui
– Whether to generate a default user interface for managing this post type. -
query_var
– False to prevent queries, or string value of the query var to use for this post type. -
rewrite
– Rewrite permalinks with this format. -
capability_type
– The string to use to build the read, edit, and delete capabilities. -
hierarchical
– Whether the post type is hierarchical. Allows parent to be specified. -
menu_position
– The position in the menu order the post type should appear in the admin. -
supports
– An alias for calling add_post_type_support() directly.
Read more about add_post_type_support in the WordPress Codex
Now our post type is setup with the settings, we need to register the post type. We register our post type by inserting the following code into our post_type function:
register_post_type(__( 'portfolio' ), $args);
Format Custom Post Type Output
We now have our custom post type created. Let's format the output, so we can get user-friendly messages. Begin by creating another function within our portfolio-post-type.php file.
// function: portfolio_messages BEGIN function portfolio_messages($messages) { $messages[__( 'portfolio' )] = array( 0 => '', 1 => sprintf(('Portfolio Updated. <a href="%s">View portfolio</a>'), esc_url(get_permalink($post_ID))), 2 => __('Custom Field Updated.'), 3 => __('Custom Field Deleted.'), 4 => __('Portfolio Updated.'), 5 => isset($_GET['revision']) ? sprintf( __('Portfolio Restored To Revision From %s'), wp_post_revision_title((int)$_GET['revision'], false)) : false, 6 => sprintf(__('Portfolio Published. <a href="%s">View Portfolio</a>'), esc_url(get_permalink($post_ID))), 7 => __('Portfolio Saved.'), 8 => sprintf(__('Portfolio Submitted. <a target="_blank" href="%s">Preview Portfolio</a>'), esc_url( add_query_arg('preview', 'true', get_permalink($post_ID)))), 9 => sprintf(__('Portfolio Scheduled For: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview Portfolio</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime($post->post_date)), esc_url(get_permalink($post_ID))), 10 => sprintf(__('Portfolio Draft Updated. <a target="_blank" href="%s">Preview Portfolio</a>'), esc_url( add_query_arg('preview', 'true', get_permalink($post_ID)))), ); return $messages; } // function: portfolio_messages END
What we have just done is create a function called portfolio_messages that takes an argument called $messages
. Following this, we are creating a variable which stores an array for all of our messages. We leave "0" blank within our array because we begin our indexing at 1 with our messages. Then finally return our array to our function.
Create Taxonomy
Finally, we need to create our taxonomy. Begin by creating another function called portfolio_filter and input the following code:
// function: portfolio_filter BEGIN function portfolio_filter() { register_taxonomy( __( "filter" ), array(__( "portfolio" )), array( "hierarchical" => true, "label" => __( "Filter" ), "singular_label" => __( "Filter" ), "rewrite" => array( 'slug' => 'filter', 'hierarchical' => true ) ) ); } // function: portfolio_filter END
We begin by registering our taxonomy and then applying the taxonomy to our custom post type portfolio. Following this, we apply the final settings of the taxonomy and input the created labels. The reason we are creating a taxonomy is because we will use it as a reference key when sorting our portfolio with Quicksand.
Now that all of our custom post type is complete along with the correct formatting and our own taxonomy, we need to finally initialise all of our code so that it will be displayed in the admin. Let's begin by adding the following code at the bottom of our file:
add_action( 'init', 'post_type' ); add_action( 'init', 'portfolio_filter', 0 ); add_filter( 'post_updated_messages', 'portfolio_messages' );
Once we have input this, we then need to open our functions.php file and insert the following line of code:
include("portfolio/portfolio-post-types.php");
We need to include our custom portfolio type into our functions.php file for the script to run when the functions of your WordPress theme are being called. Now you will see in your admin panel a section titled Portfolio with 3 sub-navigation items called "Portfolio", "Add Item", and "Filter".
Step 2 Create Portfolio Page
Now we have our entire portfolio settings complete, we need to output our portfolio items. We begin this by creating a new PHP file called portfolio.php. Firstly let's add some of the essentials for the creation of a page template:
<?php /* Template Name: Portfolio */ ?> <?php get_header(); ?> <!-- #content BEGIN --> <div id="content" class="clearfix"> // We will add our content later </div><!-- #content END --> <?php get_footer(); ?>
Now, we have our fundamental page template created we need to populate our portfolio. We need to create a page first which will act as our Portfolio page, so head to the Pages -> Add New in our Dashboard. On the right hand side, you will see a box titled Page Attributes with a drop down of Default Template, select the desired template you would like to use in our case portfolio should be selected and then select publish.
Display the Filter
Now, let's go back to editing our Portfolio page template and begin to insert the filter for our portfolio. First, we begin by wrapping the filter within an unordered list and each of the categories will be an element in our list.
<ul class="filter clearfix"> <li><strong>Filter:</strong></li> <li class="active"><a href="javascript:void(0)" class="all">All</a></li> </ul>
Let's add some PHP to our filter to automatically generate the filter categories that are being used within our portfolio.
<?php $terms = get_terms('filter', $args); $count = count($terms); $i=0; if ($count > 0) { foreach ($terms as $term) { $i++; $term_list .= '<li><a href="javascript:void(0)" class="'. $term->slug .'">' . $term->name . '</a></li>'; if ($count != $i) { $term_list .= ''; } else { $term_list .= ''; } } echo $term_list; } ?>
What we are doing here is first initialising the taxonomy we wish to get, in our case filter. Secondly, set up a count with our categories for us to increment over each element within our filter, and then apply a conditional statement to check if the count that we have set is less than 0; meaning that if there are no categories in the filter or no categories assigned to a portfolio item, nothing will be output. If there are categories in our filter then we want to alter the output for each element.
We do this by the following line within our segment of code:
$term_list .= '<li><a href="javascript:void(0)" class="'. $term->slug .'">' . $term->name . '</a></li>';
We are creating a list element to fit within our unordered list, and then setting the "href" to a blank target because Quicksand will handle the organising of content, then we set our class name to the slug of the portfolio item for consistent referencing, and finally outputting the name of the category within our filters.
Display the Portfolio Items
Brilliant, we now have a dynamic filter implemented. Now we are going to output our portfolio items. Let's begin querying our database in order to get all the posts for the portfolio post type and set up our WordPress Loop. We begin by setting up a new WP_Query object and pass the correct parameters to it.
<?php $wpbp = new WP_Query(array( 'post_type' => 'portfolio', 'posts_per_page' =>'-1' ) ); ?>
We assign our WP_Query object to a variable so we can reference our query when we are initialising our Loop. We set our post type to portfolio so we only query our custom post type which we created earlier and finally set the posts_per_page to -1. We use -1 so that there are no fixed limitations to the amount of posts per page, therefore displaying all portfolio items, if we wanted we could also enter any number and it would only display the amount of portfolio items which was entered here.
Now that we have a query object which we can reference, let's set up our Loop to output our portfolio items. We begin by inserting the following code:
<?php if ($wpbp->have_posts()) : while ($wpbp->have_posts()) : $wpbp->the_post(); ?> <?php // All of our portfolio content will be inserted in here... ?> <?php endwhile; endif; ?> <?php wp_reset_query(); ?>
Before we begin entering content into our loop, we are going to set up our featured images. Open up your functions.php file and we will add some custom featured image sizes to be output for each portfolio item.
Let's check first if the current version of WordPress handles the featured image functionality, and then set up some general settings for it to work correctly. We add support for the post-thumbnails and set a default size of 56px by 56px.
if ( function_exists( 'add_theme_support' ) ) { add_theme_support( 'post-thumbnails' ); set_post_thumbnail_size( 56, 56, true ); }
Then we want to add our own custom thumbnail sizing. Insert the following code on a line below: set_post_thumbnail_size
add_image_size( 'portfolio', 295, 150, true );
This method allows you to create your own thumbnail size by first setting the reference name for the thumbnail, then the width and height and finally if the thumbnail should hard crop the image to fit the size specified. You can alter the sizes of your featured image to fit with your layout; with the purpose of this tutorial I have a 3 column grid layout.
Now that we have our Featured Image set up, we are going to head back to our portfolio page template and output the portfolio item featured image.
As the organisation for each portfolio item is best handled by an unordered list, we will first create one and then output our featured image which we have just setup. Insert the following code inside your WordPress Loop:
<ul class="filterable-grid clearfix"> <li> <?php if ( (function_exists('has_post_thumbnail')) && (has_post_thumbnail()) ) : ?> <?php the_post_thumbnail('portfolio'); ?> <?php endif; ?> <p><a href="<?php the_permalink(); ?>"><?php echo get_the_title(); ?></a></p> </li> </ul>
We initially check if the theme supports the thumbnail function. If the theme supports this feature then it will output the feature image at the dedicated thumbnail we have specified earlier. After outputting our featured image, we then output the title of the Portfolio item directly below the image.
Connect Portfolio Items & Filter
We need to tweak the different elements of each portfolio list item to ensure that the referencing for each portfolio is correct to the categories the item is assigned to. For this, we will first need to get the categories from our taxonomy. Insert the following code within your Loop:
<?php $terms = get_the_terms( get_the_ID(), 'filter' ); ?>
Next, we are going to add some attributes to our list element (li
). We begin by adding a data-id
to our list item, to provide a unique identity to each of the portfolio items. We are also going to add a data-type
; this will act as our referencing to our filter. Let's replace our opening list element (li
) with the following code:
<li data-id="id-<?php echo $count; ?>" data-type="<?php foreach ($terms as $term) { echo strtolower(preg_replace('/\s+/', '-', $term->name)). ' '; } ?>">
We apply a count to our data-id
, and when looping through each item, the count will be increased (we will add the count shortly). We then loop over each category in our taxonomy and apply a regular expression to find the spaces and replace it with a "-" to match the slug of the category and then finally put a blank space at the end, so we are able to apply more than one category to a portfolio item.
Finally, we are going to ensure that we increment our count and provide a unique reference to each of our portfolio items. We need to add the following code just before we end the loop:
<?php $count++; ?>
Final Code for Displaying Portfolio
<ul class="filterable-grid clearfix"> <?php $wpbp = new WP_Query(array( 'post_type' => 'portfolio', 'posts_per_page' =>'-1' ) ); ?> <?php if ($wpbp->have_posts()) : while ($wpbp->have_posts()) : $wpbp->the_post(); ?> <?php $terms = get_the_terms( get_the_ID(), 'filter' ); ?> <li data-id="id-<?php echo $count; ?>" data-type="<?php foreach ($terms as $term) { echo strtolower(preg_replace('/\s+/', '-', $term->name)). ' '; } ?>"> <?php if ( (function_exists('has_post_thumbnail')) && (has_post_thumbnail()) ) : ?> <?php the_post_thumbnail('portfolio'); ?> <?php endif; ?> <p><a href="<?php the_permalink(); ?>"><?php echo get_the_title(); ?></a></p> </li> <?php $count++; ?> <?php endwhile; endif; ?> <?php wp_reset_query(); ?> </ul>
Step 3 jQuery & Quicksand
We're making progress now, but before we continue we need to go and download some jQuery scripts. We need to download the following scripts:
- jQuery 1.7 (version included with WordPress 3.3.1)
- Quicksand Plugin (latest version from GitHub)
- Easing Plugin (version 1.3)
We also need to create a JavaScript file to handle all of our custom jQuery that we will be writing shortly. So let's create a blank JavaScript file called jquery.custom.js. Now that we have all of our essential scripts, let's open our functions.php and create a blank function called register_js. Once we have our blank function, we are going to insert our scripts using the wp_register_script and wp_enqueue_script methods. First, we must check that we're not in the admin to ensure the scripts are only loaded on the front end. Insert the following code into our function:
// Register our scripts function register_js() { if ( !is_admin() ) { wp_register_script( 'quicksand', get_template_directory_uri() . '/js/jquery.quicksand.js', 'jquery' ); wp_register_script( 'easing', get_template_directory_uri() . '/js/jquery.easing.1.3.js', 'jquery' ); wp_register_script( 'custom', get_template_directory_uri() . '/js/jquery.custom.js', 'jquery', '1.0', true ); wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'quicksand' ); wp_enqueue_script( 'easing' ); wp_enqueue_script( 'custom' ); } }
First with wp_register_script we specify a handle as our first argument for reference when enqueuing the scripts, then add the source link to the script as our second argument (this applies to each registration of a script). We also specify jquery as a dependency to load WordPress' included version of jQuery when we enqueue the script.
Once we have registered all of our scripts, we then enqueue them by using wp_enqueue_script. We pass all the handles that we used when registering as a reference to enqueue our scripts. Finally, we need to initialise our function by adding the following code in our functions.php file:
add_action('init', 'register_js');
Writing Quicksand
Now that we have all of our scripts in place, we can begin writing our jQuery custom script for the handling of Quicksand. Let's open up our jquery.custom.js script and let's set up the environment by inserting the following code:
jQuery(document).ready(function() { // We will insert our quicksand script in here }); // END OF DOCUMENT
Now we have our script structure, we will create a function called portfolio_quicksand and only execute if the Quicksand plugin exists.
function portfolio_quicksand() { // All of our quicksand handling will happen in this function } if(jQuery().quicksand) { portfolio_quicksand(); }
I will break down the following into smaller steps for you to understand all that is taking place when creating a Quicksand portfolio. Let's begin by setting up our variables. Insert the following code into our portfolio_quicksand function:
var $filter; var $container; var $containerClone; var $filterLink; var $filteredItems;
We will be using these variables more frequently, so it's always a good way to get a solid foundation of variables set up. Next we are going to assign our variables:
$filter = $('.filter li.active a').attr('class'); $filterLink = $('.filter li a'); $container = $('ul.filterable-grid'); $containerClone = $container.clone();
We first set up our filter to the unordered list class from our portfolio page template. Secondly, we set up a filterLink; this will act as our clicked item within our filter. Then we need to assign our container of our portfolio items, and finally we require a cloned version of our container, to manipulate the data with Quicksand.
Next, we are going to write our click function, so when a user selects a category the container should be manipulated and the output of the content should display. Let's start by calling a click function on our filterLink:
$filterLink.click(function(e) { // We will add the content for this function now... });
Now let's handle the active state of the list element. We begin by first removing any class with a current active state, then searching through the filter and splitting the filter into separate items, and finally applying an active class to the clicked item (category):
$('.filter li').removeClass('active'); $filter = $(this).attr('class').split(' '); $(this).parent().addClass('active');
This will help when styling your filter, because you will be able to provide active states for when a user has selected a category.
Moving on, we will handle a condition for the filtering of our data. We begin by first checking if all has been selected. If all has been selected then display all the elements within our container, else display the items within the container which has been selected by the filter.
Previously, when we were creating our portfolio page template and we assigned a data-type
to each of our portfolio items, this is where we will be using it as a reference key to find our selected data.
if ($filter == 'all') { $filteredItems = $containerClone.find('li'); } else { $filteredItems = $containerClone.find('li[data-type~=' + $filter + ']'); }
Finally, we call the Quicksand method, and pass our filteredItems and all of our animation options:
$container.quicksand($filteredItems, { duration: 750, easing: 'easeInOutCirc', adjustHeight: 'dynamic' });
Final Code for Our Quicksand
function portfolio_quicksand() { // Setting up our variables var $filter; var $container; var $containerClone; var $filterLink; var $filteredItems // Set our filter $filter = $('.filter li.active a').attr('class'); // Set our filter link $filterLink = $('.filter li a'); // Set our container $container = $('ul.filterable-grid'); // Clone our container $containerClone = $container.clone(); // Apply our Quicksand to work on a click function // for each of the filter li link elements $filterLink.click(function(e) { // Remove the active class $('.filter li').removeClass('active'); // Split each of the filter elements and override our filter $filter = $(this).attr('class').split(' '); // Apply the 'active' class to the clicked link $(this).parent().addClass('active'); // If 'all' is selected, display all elements // else output all items referenced by the data-type if ($filter == 'all') { $filteredItems = $containerClone.find('li'); } else { $filteredItems = $containerClone.find('li[data-type~=' + $filter + ']'); } // Finally call the Quicksand function $container.quicksand($filteredItems, { // The duration for the animation duration: 750, // The easing effect when animating easing: 'easeInOutCirc', // Height adjustment set to dynamic adjustHeight: 'dynamic' }); }); }
Step 4 Lightbox Integration (Additional Extra)
Amazing right, you should now have a fully functionally Quicksand portfolio, but let's not stop just there. I'm going to put an additional extra, this is totally optional but it could become a favourite feature, and that's Lightbox. We will be using the jQuery plugin called PrettyPhoto for our Lightbox integration.
First thing we are going to do is download the PrettyPhoto plugin.
- PrettyPhoto v3 (or latest version)
Once we have downloaded our PrettyPhoto files, we will first copy over the PrettyPhoto images, which will be in the images folder and then you need to copy the folder titled PrettyPhoto into our theme. We also need to copy over the CSS and PrettyPhoto's JavaScript file, so let's copy them over to the appropriate folders in our theme.
Now that we have all of our files in place, we need to initialise them within our theme. Within our functions.php file, we will create another function to handle our styles and we will call this function register_css. Then we will register our styles and enqueue our styles, thus insert the following code into your functions.php file:
// Register our styles function register_css() { if (!is_admin()) { wp_register_style( 'prettyPhoto', get_template_directory_uri() . '/css/prettyPhoto.css' ); wp_enqueue_style( 'prettyPhoto' ); } } add_action( 'init', 'register_css' );
We have all of our files in place and they are being initialised by our theme. Now we need to make use of this and implement Lightbox into our theme. Let's open up our portfolio.php (portfolio page template) and add some code to our Featured Image.
First, we need to get a large image of the featured image which has been set. This will then act as the fullsize image when the user clicks on the image and PrettyPhoto loads. Inside our WordPress Loop, we need to insert the following code:
<?php $large_image = wp_get_attachment_image_src( get_post_thumbnail_id(get_the_ID()), 'fullsize', false, '' ); $large_image = $large_image[0]; ?>
The code we have inserted will find the current post within the loop and find the original source of the image and then find the fullsize version of the image. Once we have returned our full size image, we will force the image to be stored in the array index of 0. This is used for no overrides or duplicates with our full size images.
Once we have our full size image accessible, we will now initialise PrettyPhoto on our featured image. The following code will link the fullsize image to the featured image of the portfolio item and pass the reference to PrettyPhoto, replace the code where you created your featured image with the following:
<a rel="prettyPhoto[gallery]" href="<?php echo $large_image ?>"><?php the_post_thumbnail('portfolio'); ?></a>
Great, we have got all of our files and scripts in place, we have got the full size image for our featured image and we have referenced our featured image to our full-size image with PrettyPhoto. Next, we need to write our JavaScript to make the Lightbox appear and work.
Let's head back to our jquery.custom.js file and create another blank function to handle our PrettyPhoto:
function lightbox() { // Our Lightbox functioning will be added now... } if(jQuery().prettyPhoto) { lightbox(); }
Now that we have our function, we will initialise PrettyPhoto. We do this by adding the following code within our Lightbox function:
jQuery("a[rel^='prettyPhoto']").prettyPhoto({ animationSpeed:'fast', slideshow:5000, theme:'pp_default', show_title:false, overlay_gallery: false, social_tools: false });
You can read the full documentation of all the parameters that PrettyPhoto will accept in the use of the plugin at: PrettyPhoto jQuery Lightbox Clone
So, it's all done! Lightbox implementation into your WordPress theme, but wait let me guess when you click on the filter and use Quicksand; the Lightbox is no longer working. That's because we need to alter our Quicksand script and pass one more small piece of code to make sure that Lightbox works even when we filter through our portfolio.
So let's fix this small problem by adding the following script to our portfolio_quicksand function within our jquery.custom.js file:
$container.quicksand($filteredItems, function () { lightbox(); } );
What we do here is call the Quicksand plugin once more and pass a function within this call to our Lightbox function. So every time Quicksand filters the content, the Lightbox function is called applying the PrettyPhoto to each image.
Step 5 Pagination Integration (Additional Extra)
Many people love having the use of Quicksand, but some people like the use of both Quicksand and pagination within their portfolios. This is another additional extra to create pagination within your portfolio. I will be using the WordPress plugin: WP_PageNavi.
Let's first install and activate the plugin. Head to the Plugins -> Add New page in our admin section and search WP_PageNavi, once found click Install Now and Activate Plugin once installed.
Now that we have our plugin setup, let's open up our portfolio page template and make some modifications to our file.
First, we need to setup our page to allow pagination. We do this by inserting the following segment of code before we query our database:
$paged = get_query_var('paged') ? get_query_var('paged') : 1;
Once we have our pagination initialised, we need to modify the database query. We change the post_per_page to a number to display a maximum number of posts which will be displayed on each page. Then we pass a new parameter to our query paged and reference this to our code segment which allowed us to paginate the page, as the following code demonstrates:
$wpbp = new WP_Query(array( 'post_type' => 'portfolio', 'posts_per_page' =>'2', 'paged' => $paged ) );
Great, we have a portfolio with pagination. We just need some controls to help us with the navigation of each page. The following code checks if the WP_PageNavi plugin is installed and then initialises the wp_pagenavi with the query of the database passed as a parameter. We then reset our postdata and all content is correctly paginated.
<?php if(function_exists('wp_pagenavi')) { wp_pagenavi(array( 'query' => $wpbp ) ); wp_reset_postdata(); } ?>
That's it! You will have a fully functional portfolio with Quicksand, Lightbox and Pagination.
Conclusion
Give yourself a pat on the back! You have successfully created a Quicksand portfolio with WordPress. All the hard work is done and you can implement it with any work you develop.
I would like to say a HUGE thank you for spending the time to read my tutorial, I hope it helped. Please feel free to leave comments and I will try my best to assist and answer them.
Comments