A few months ago I wrote a post on how to integrate Isotope with WordPress. Since then, I’ve received some requests on showing how to limit it to one category. In this tutorial I will show how to add the Isotope code and scripts to a template, filtering the posts that belong to one category by it’s sub-categories.
You will notice that most steps are the same as with the original tutorial, but I have left them here, so people won’t have to go back and forth between articles. I’ll highlight the lines of code that differ from the first article.
- Download the script from the Isotope repository, and upload it to your theme’s folder (for example /js/libs/jquery.isotope.min.js)
- Add a list of sub-categories of my category 37 (here’s a tutorial on how to find the ID for your category). This list will serve as filters (following the filtering instructions in istotope):
<ul id="filters"> <li><a href="#" data-filter="*">Everything</a></li> <?php $terms = get_terms('category', array('parent' => 37)); // you can use any taxonomy, instead of just 'category' $count = count($terms); //How many are they? if ( $count > 0 ){ //If there are more than 0 terms foreach ( $terms as $term ) { //for each term: echo "<li><a href='#' data-filter='.".$term->slug."'>" . $term->name . "</a></li>\n"; //create a list item with the current term slug for sorting, and name for label } } ?> </ul>
- Make a custom loop to load all the posts that match the sub-categories. Each blog posts must share a class (in my case, I used ‘item’), and additional classes to filter (from the list of categories from Setp 2):
<?php $terms_ID_array = array(); foreach ($terms as $term) { $terms_ID_array[] = $term->term_id; // Add each term's ID to an array } $terms_ID_string = implode(',', $terms_ID_array); // Create a string with all the IDs, separated by commas $the_query = new WP_Query( 'posts_per_page=50&cat='.$terms_ID_string ); // Display 50 posts that belong to the categories in the string ?> <?php if ( $the_query->have_posts() ) : ?> <div id="isotope-list"> <?php while ( $the_query->have_posts() ) : $the_query->the_post(); $termsArray = get_the_terms( $post->ID, "category" ); //Get the terms for this particular item $termsString = ""; //initialize the string that will contain the terms foreach ( $termsArray as $term ) { // for each term $termsString .= $term->slug.' '; //create a string that has all the slugs } ?> <div class="<?php echo $termsString; ?> item"> <?php // 'item' is used as an identifier (see Setp 5, line 6) ?> <h3><?php the_title(); ?></h3> <?php if ( has_post_thumbnail() ) { the_post_thumbnail(); } ?> </div> <!-- end item --> <?php endwhile; ?> </div> <!-- end isotope-list --> <?php endif; ?>
- Go check. At this point your page should have a list with all your categories, and a bunch of posts. View the page source to make sure the blog posts have the proper classes (‘item’, plus all the categories it belongs to).
- Create a file with the necessary JavaScript to launch and set up Isotope, and place it in your theme folder (for example, /js/isotope.js):
jQuery(function ($) { var $container = $('#isotope-list'); //The ID for the list with all the blog posts $container.isotope({ //Isotope options, 'item' matches the class in the PHP itemSelector : '.item', layoutMode : 'masonry' }); //Add the class selected to the item that is clicked, and remove from the others var $optionSets = $('#filters'), $optionLinks = $optionSets.find('a'); $optionLinks.click(function(){ var $this = $(this); // don't proceed if already selected if ( $this.hasClass('selected') ) { return false; } var $optionSet = $this.parents('#filters'); $optionSets.find('.selected').removeClass('selected'); $this.addClass('selected'); //When an item is clicked, sort the items. var selector = $(this).attr('data-filter'); $container.isotope({ filter: selector }); return false; }); });
- There is some optional, but recommended CSS that you should add to animate the filtering. Place a CSS file with the code in your theme folder (for example /css/isotope.css). Feel free to add additional styles to make your posts look nice:
/* Start: Recommended Isotope styles */ /**** Isotope Filtering ****/ .isotope-item { z-index: 2; } .isotope-hidden.isotope-item { pointer-events: none; z-index: 1; } /**** Isotope CSS3 transitions ****/ .isotope, .isotope .isotope-item { -webkit-transition-duration: 0.8s; -moz-transition-duration: 0.8s; -ms-transition-duration: 0.8s; -o-transition-duration: 0.8s; transition-duration: 0.8s; } .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: -o-transform, 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; } /* End: Recommended Isotope styles */
- In functions.php, load the scripts and CSS:
function add_isotope() { wp_register_script( 'isotope', get_template_directory_uri().'/js/libs/jquery.isotope.min.js', array('jquery'), true ); wp_register_script( 'isotope-init', get_template_directory_uri().'/js/isotope.js', array('jquery', 'isotope'), true ); wp_register_style( 'isotope-css', get_stylesheet_directory_uri() . '/css/isotope.css' ); wp_enqueue_script('isotope-init'); wp_enqueue_style('isotope-css'); } add_action( 'wp_enqueue_scripts', 'add_isotope' );
That’s it!