Filter Posts by Taxonomy using Isotope
Click on the filter buttons to narrow down the posts based on taxonomy, and to get an idea of the result we'll achieve in this post...
What are Canonical URLs and how to use them?
גוטנברג - העורך החדש של וורדפרס
Gutenberg – The New WordPress Editor
טיפול במוצרים שאינם זמינים בחנות (או אזלו מהמלאי) מבחינת SEO
Handling unavailable products (or out of stock) in terms of SEO
היררכיה של תבניות עמוד Single Pages
The Hierarchy of Page Templates in WordPress
לולאת for בג׳אווה סקריפט - JavaScript for Loop
JavaScript for Loop – Basic Explanation & Examples
קו מפריד עם אלמנט באמצע – כיצד עושים זאת ב CSS?
Separator Line with an Element in the Middle in CSS
עיכוב פריסת Javascript לסרטוני YouTube
Defer JavaScript for Youtube Videos
כיצד לשתף עמוד/פוסט במצב טיוטה עם משתמשים אנונימים
How to Share a Draft Post with Anonymous Users
על התכונה Grid Areas של CSS Grid בהרחבה
Expanding on the CSS Grid’s “Grid Areas” feature
קידום בגוגל - אופטימיזציה לתוכן (On-Page SEO) - חלק ב'
On-Page SEO Optimization – Rank Higher on Google – Part 2
מחפשים מפתח וורדפרס? כל המידע שאתם צריכים לדעת
Looking for a WordPress developer? All the information you need to know
עיצוב פסי גלילה (Scrollbars) עם CSS
Styling Scrollbars with CSS
איך לבצע אנימציה (Transition) על Gradients?
How to Perform Animation (Transition) on Gradients?
The way Google and Search Engines Consider URLs
מהו קובץ robots.txt וכיצד להשתמש בו נכון
What is the robots.txt file and how to use it correctly
רישום של שדות ב Advanced Custom Fields  באמצעות PHP
Registering ACF Fields with PHP
מדריך גוגל תג מנג׳ר (GTM) למתחילים - מדוע וכיצד להשתמש בו?
Google Tag Manager for Beginners: Why and How to Use It (2024)
מהם UTM Parameters, מדוע צריך אותם וכיצד להשתמש בהם?
What are UTM Parameters, Why and How to Use them?
אופטימיזציה לקונפיגורציה של וורדפרס באמצעות wp-config.php
Optimization WordPress Configuration through wp-config.php
wordpress-pagination-no-plugin
Adding Numbered Pagination in a WordPress Template
הוספה אוטומטית של מספר מוצרים לעגלת הקניות
Adding Products to the Shopping Cart Through a Link
איך לגבות אתר וורדפרס באמצעות UpdraftPlus
How to Backup and Restore a WordPress Website? (With and Without a Plugin)
בדיקת ביצועי האתר באמצעות WebPageTest
How to Use WebPageTest to Check Site Performance
מה זה Facebook Pixel (פייסבוק פיקסל) ואיך להוסיפו לוורדפרס?
What is Facebook Pixel & How to add it in WordPress?
מה זה DNS (Domain Name System)?
What is DNS (Domain Name System)?
כיצד לקשר את Google Search Console לגוגל אנליטיקס
How to Link Google Search Console to Analytics 4
עיצוב האות הראשונה ב CSS בעזרת first-letter::
Styling the First Letter with CSS ::first-letter
הוקים בוורדפרס - Wordpress Hooks
WordPress Hooks for Beginners
Transferring UTM Parameters Between Pages / Domains
ההשפעה של קישורי Nofollow, Sponsored & UGC על SEO
The SEO impact of Nofollow, Sponsored & UGC links
מספר מילים על ACF Synchronized JSON
A few words about ACF Synchronized JSON
ביטול RSS Feed (פיד) באתרי וורדפרס
Disabling RSS Feed on WordPress Sites
Search

Create an Elements Filter with Isotope Library

In this post, we will show how to create a filter with Isotope that allows filtering elements based on any attribute, in our case, we will enable filtering posts by taxonomy.

To create the filter we gonna use Isotope which allows convenient and fast filtering and sorting of information.

I want to mention from the outset that I won’t go too deep into the code in this post, so this post is intended for those with some prior knowledge and basic understanding.

Isotope has many options; I won’t elaborate on them, and I won’t touch on the sorting aspect at this stage, only the filtering option. If you have questions on the topic, feel free to ask in the post comments.

It’s important to note that the Isotope library we’ll use is free for personal use only; for commercial projects, you need to purchase a license.

If you’re not interested in filtering and only need Masonry or layout options, you can use the free Masonry library, and the usage will be very similar to what you see in this post.

Anyway, let’s see how I implemented the example above. In contrast to that, we will see how to do this in a new page template on your site. Let’s start…

1. Create a New Page Template

In order to create your custom page template, create a new PHP file in the main template directory, let’s call it blog-template.php.

Now add the following code at the top (avoid spaces or empty lines before this code):

<section class="isotope-filter">
    <div class="filters">
        <div class="tag-filters__desktop">
            <ul class="filter-btns">
                <li>
                    <button data-filter="*">הכל</button>
                </li>
                <?php

                $terms = get_terms(array(
                    'taxonomy' => 'my_taxonomy',
                    'parent' => 0,
                    'childless' => 'true',
                    'hide_empty' => 'true'
                ));

                foreach ($terms as $term) { ?>
                    <li>
                        <button data-filter=".<?php echo $term->slug; ?>"><?php echo $term->name; ?></button>
                    </li>
                    <?php
                }

                ?>
            </ul>
        </div>
    </div>
    <div class="grid">
        <?php

        global $post;

        $args = array(
            'post_type' => 'post',
            'posts_per_page' => 24,
            'post__not_in'   => array($post->ID),
            'ignore_sticky_posts' => true,
            'orderby'   => 'rand'
        );

        $custom_query = new WP_Query($args);

        while ($custom_query->have_posts()) : $custom_query->the_post();

            $terms = get_the_terms($post->ID, 'my_taxonomy');
            // get the first term
            $term = array_shift($terms);
            ?>

            <div class="grid-item <?php echo $term->slug; ?>">
                <div class="grid-item-inner">
                    <div class="my-title"><?php the_title(); ?></div>
                    <?php the_post_thumbnail(); ?>
                    <?php echo wp_trim_words( get_the_excerpt(), 18 ) ?>
                </div>
            </div>

        <?php endwhile; ?>

        <?php wp_reset_postdata(); // reset the query ?>

    </div>
</section>

A few words about the code above:

A. In lines 10-22, we use the get_terms function to get the terms in the my_taxonomy taxonomy and display them. These terms will be the options for our filter, and the filtering will be done based on these.

If you want to filter by categories (which are taxonomies for everything), just change my_taxonomy in line 11 to category, and the result will be all the categories.

Note that in line 19, we print each of the buttons, and each of them has an attribute named data-filter with a dot (‘.‘) and the slug of the term as its value.

For the “All” button that displays all posts, the data-filter should contain an asterisk (*).

B. In lines 28-62, we print an element with the class grid. We use a simple loop to display all posts of the default WordPress content type post.

Of course, you can choose to display any custom content type by changing the post type in line 32.

Each of these posts has the class grid-item (line 50), accompanied by an additional class that is exactly the same as the identifier of the terms displayed in our filter options, meaning the identifier of the taxonomy (or category) of that post.

So, if the filter button for the term woocommerce looks like this:

<button data-filter=".woocommerce">WooCommerce and Online Stores</button>

The markup of the post assigned to this taxonomy/category looks like this:

<div class="grid-item woocommerce">
    <div class="grid-item-inner">
        ...
    </div>
</div>

Note that in this case, we assume that each post is associated with only one taxonomy/category!

C. In line 50, we reset WordPress’s loop. Explanation on this topic in a post I wrote about several ways to reset the WordPress
loop
.

2. Load the Necessary Files for Isotope

The following code loads three JavaScript files using WordPress’s wp_enqueue_script function, which you are probably familiar with.

The first one loads the Isotope library, the second is a library called imagesLoaded, which ensures that if images are not loaded, there won’t be an unwanted flicker between the
displayed elements (posts).

The third is an additional JS file where we implement Isotope, set its options, and apply it to the container with all the posts.

Note that there is a dependency between the files in terms of the loading order:

function isotope_assets() {
    if ( is_page_template('page-templates/blog-template.php') ) {

        wp_enqueue_script(
            'isotope',
            get_stylesheet_directory_uri() . '/js/isotope.pkgd.min.js',
            array('jquery'),
            '1.0.1',
            true
        );

        wp_enqueue_script(
            'images-loaded',
            get_stylesheet_directory_uri() . '/js/imagesloaded.pkgd.min.js',
            array('isotope'),
            '1.0.1',
            true
        );

        wp_enqueue_script(
            'isotope-init',
            get_stylesheet_directory_uri() . '/js/isotope-init.js',
            array('images-loaded'),
            '1.0.1',
            true
        );

    }
}
add_action('wp_enqueue_scripts', 'isotope_assets');

The conditional check ensures that we load these files only in the relevant page template – in our case, the template using the blog-template.php file. You should stick to this method and load libraries and assets only when needed for performance and site loading time.

Take a look at the file that implements Isotope

(function ($) {

    var $grid = $('.grid').imagesLoaded( function() {
        // init Isotope after all images have loaded
        $grid.isotope({
            // options...
            itemSelector: '.grid-item',
            layoutMode: 'fitRows',
            originLeft: false
        });
    });
    
    $('.filter-btns').on( 'click', 'button', function() {
        var filterValue = $( this ).attr('data-filter');
        $grid.isotope({ filter: filterValue });
    });

}(jQuery));

In line 3, we ensure that the images of the elements have loaded using the imagesLoaded library before running the function that implements Isotope on an element with the grid class.

Isotope comes with many parameters, events, and methods, which we won’t go into (check the official documentation). In our case, we specify to Isotope that the elements inside the container have the class grid-item.

The second parameter we set is the choice of layout in which the elements will be displayed. The third parameter ensures that the grid works from right to left (RTL).

From lines 12-15, a simple function is set to ensure that when clicking on one of the filter buttons, the attribute of the button that we set in the Markup using data-filter will be passed to Isotope, and the filtering will be done based on this attribute.

Let’s design the filtering buttons a bit and set the size of the elements in each row along with their styling. Note that these are up to you and can be changed as usual with CSS. In any case, here is the CSS I used:

.isotope-filter {
    padding-top: 130px;
}

.filter-btns {
    display: flex;
    flex-wrap: wrap;
    margin: 20px 20px 40px;
    justify-content: space-evenly;
    border-width: 1px 0;
}

.filter-btns li {
    list-style-type: none;
    display: flex;
    margin: 0 0 10px;
    border: 1px solid #ccc;
    align-items: center;
    transition: all .2s;
    background: white;
    border-radius: 50px;
}

.filter-btns li:hover {
    background: #616161;
    color: white;
}

.filter-btns li:last-child {
    margin-left: 0;
}

.filter-btns button {
    background: #0000;
    border: none;
    font-size: 12px;
    width: 100%;
    padding: 0 15px;
    color: inherit;
    height: 50px;
}

.my-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 14px;
    min-height: 42px;
    line-height: 20px;
}

.grid-item-inner img {
    margin-bottom: 10px;
}

.grid-item-inner {
    padding: 20px 20px;
    background: #fff;
    border-radius: 20px;
    border: 1px solid #eee;
}

.grid-item {
    width: 47%;
    margin: 1.5%;
}

@media (min-width: 1200px) {
    .grid-item {
        width: 22%;
        margin: 1.5%;
    }

    .filter-btns button {
        font-size: 13px;
        padding: 0 20px;
    }
}

You can see that through Media Queries, we set the width of the elements above 1200px to be 22% (four in a row) and below that, two in a row, with matching margins.

Of course, there are various ways to achieve this, and this is just for demonstration purposes. Hope the post helps you; questions and ideas are welcomed in the comments only…

Roee Yossef
Roee Yossef

I develop websites & custom WordPress themes by design. I love typography, colors & everything between, and aim to provide high performance, seo optimized websites with a clean & semantic code.

0 Comments...

Leave a Comment

Up!
Blog