![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts.png)
You’ve most likely seen these A-Z filter areas on your travels. They’re pretty useful if have a site that contains a lot of index type posts, such as users in a membership site, a book review site, or a movie blog, etc and you would like to offer users a simple way to filter through this content by displaying an alphabet menu that they can filter by letter or number.
Demo can be found here.
Create a template file in WordPress
Let’s create a template page called A-Z, upload to your website and attach this a page.
- az-template.php
<?php /* Template name: A-Z */
get_header(); ?>
<div id="main-area">
<div class="wrapper">
<div <?php post_class(); ?>>
// All of our code will go here
</div>
</div>
</div>
<?php get_footer(); ?>
Return all posts and get first letter from each post
We are going to create a custom loop to pull in all of the posts we want to show. You will want to tweak your options to suit your needs but In my case, I want posts, in the tutorial category, and the posts_per_page -1 option will display every post.
- az-template.php
<?php
$filter_args = array
(
'post_type' => 'post',
'posts_per_page' => -1,
'category_name' => 'tutorial',
);
Next, we will create a new WP_Query object called $tutorial_posts with our $filter_args array options. after that, we will create an empty array called $posts_array to store the first letter of our posts.
- az-template.php
$tutorial_posts = new WP_Query($filter_args);
$posts_array = array();
Now, we just need to run our custom loop with our $tutorial_posts object to grab all posts, convert each post to lower case, and get the first letter from each post.
- az-template.php
while ( $tutorial_posts->have_posts() ) : $tutorial_posts->the_post();
$posts_array[] = strtolower(get_the_title()[0]);
endwhile;
After this loop has finished, the $posts_array will hold all of the first characters of our posts. if we were to var_dump this array, we would see the following:
- var_dump
array(14) {
[0]=>
string(1) "e"
...
[13]=>
string(1) "r"
}
Building our A-Z filter list
Now we have all of the first characters that are available to us – we can start to build the A-Z filter.
First, we are going to generate the list of A-Z characters (with the # symbol before the loop for numbers).
- az-template.php
$alphabet_array = range('a', 'z'); // Generate our A-Z list of characters
?>
<ul id="a-z">
<li>#</li> // Include our # for numbers
<?php foreach ($alphabet_array as $letter) // Loop through the alphabet and spit out a list item with the letter
{
echo "<li>" . $letter . '</li>';
}
?>
</ul>
After running this code, we are left with an unformatted list. We just need to style it.
Styling the list
- style.css
#a-z {
float: left;
width: 100%;
margin-bottom: 25px;
display: flex;
flex-direction: row;
}
ul#a-z li {
flex-grow: 1;
padding: 7px;
text-align: center;
background: #dadbdc;
color: #fff;
text-transform: uppercase;
border-left: 2px solid #fff;
}
Now we are left with a nicely formatted list like below.
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts-2.png)
Enabling characters in our list
So, we have a nice looking a-z list, but we can’t tell what characters are available to click and interact with. We need to fix that.
Checking if any posts begin with a number
The first thing we do before the foreach loop is run is to check if any posts begin with a number, so we are going to create a $number_array.
- az-template.php
$alphabet_array = range('a', 'z');
$number_array = range(0, 9); // New array created (0-9)
And then using PHP’s array_intersect function, we can check if any characters from the $posts_array have numbers from the numbers array in it. If posts begin with a number, we will apply a class called active to the list item, if not, we will just display the list item.
From here I will also start adding a custom data attribute named data-letter to our list items to be used later on when we want to filter the posts.
- az-template.php
if(count(array_intersect($posts_array, $number_array)) > 0)
{
echo "<li class=\"active\" data-letter=\"#\">#</li>";
}
else
{
echo "<li data-letter=\"#\">#</li>";
}
// foreach loop
If any of our posts begin with a number, the active class will be added.
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts-3.png)
Enabling available letters
Now we need to go back to our foreach loop and check if any of our post’s first letters are in our alphabet array.
- az-template.php
foreach ($alphabet_array as $letter)
{
if (in_array($letter, $posts_array))
{
echo "<li class=\"active\" data letter=".$letter.">$letter</li>"
}
else
{
echo "<li data-letter=".$letter.">$letter</li>";
}
}
The A-Z list will now include available list items with the active class. Let’s create an .active class in our CSS to make this darker than the rest.
- style.css
ul#a-z li.active {
background: #9c9c9c;
cursor: pointer;
}
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts.-4.png)
We now have a nifty A-Z list! Up next, we are going to build our index of posts area underneath.
Building our posts index
We are going to reuse our previous $tutorial_posts object to load all of our posts within our next WordPress loop. Explanation of what is going below.
- az-template.php
/**
* We create a counter and give it a value of -1 as we will use this counter
* with the $posts_array and array's indexes begin at 0, so this just syncs
* everything up.
*/
$i = -1; ?>
<ul id="posts-results">
<?php while ( $tutorial_posts->have_posts() ) : $tutorial_posts->the_post(); // Loop through all posts
$i++; // Increment counter by 1 on each loop iteration
if(is_numeric($posts_array[$i])) // Check if any of the posts are numeric
{
echo "<li data-letter=\"#\">"; // If number, add # to data-letter attribute
echo "<a href=".get_the_permalink().">";
echo get_the_title();
echo "</a>";
echo "</li>";
}
else // If posts begin with letter
{
echo "<li data-letter=".$posts_array[$i].">"; // Add letter to each data-letter attribute
echo "<a href=".get_the_permalink().">";
echo get_the_title();
echo "</a>";
echo "</li>";
} ?>
<?php endwhile; ?> // End while loop
</ul>
What’s returned now is all of our posts, unformatted. We just need to style posts these with the below CSS.
- style.css
#posts-results a {
border-bottom: 1px solid #ccc;
display: block;
padding: 10px 0;
}
So we are left with this.
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts-5.png)
Using JavaScript to add the filtering functionality
The way we are going to filter our posts is first hiding all posts and using a show class to display them. So before we create our JavaScript, let’s add some CSS.
- style.css
#posts-results li { /* By default, hide all posts */
display: none;
}
#posts-results li.show { /* When a show class is used, this displays posts */
display: block;
}
ul#a-z li.current { /* This class will be used to highlight the current A-Z list item */
background: #de466c;
}
We can now create our jQuery code to show the first few posts, depending on what character is available and then highlight the correct A-Z character.
- main.js
jQuery(document).ready(function()
{
"use strict";
let initial_first_letter = jQuery('#a-z li.active:eq(0)').data('letter'); // Create var to get the data-letter of the first active list item
let posts_results_li = jQuery("#posts-results li"); // Create var for all post result list items
// Initial load of page
jQuery("#posts-results li[data-letter="+initial_first_letter+"]").addClass('show'); // Show post results with first available active class added
jQuery('#a-z li.active:eq(0)').addClass('current'); // Add the current class to the first item that has the active class
});
On initial load of the page we can see that the first character available is a number so the # in our A-Z list is highlighted, and secondly all posts are hidden and only posts that begin with a number will display. If no, posts began with a number, the next available character would be highlighted and shown.
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts-6.png)
Make the A-Z list interactive
The final thing we need to do is to allow our users to interact with the A-Z menu and show posts from different characters.
- main.js
let click_first_char; // Create var to hold what character is clicked
// Clicking A-Z list items
jQuery('#a-z li.active').click(function() // User clicks A-Z list item
{
jQuery(posts_results_li).removeClass('show'); // Hide all posts
jQuery('#a-z li.active').removeClass('current'); // Remove current class from all A-Z list items
click_first_char = jQuery(this).data('letter'); // Add clicked character to click_first_char variable
jQuery(this).addClass('current'); // Add current class to clicked A-Z list item
jQuery("#posts-results li[data-letter="+click_first_char+"]").addClass('show'); // Show posts that match clicked character
});
Last few bits and wrap up
The very last thing I would like to add here are two features to make this nice and user friendly:
- A show all ‘link’
- A title showing the current character in use
After our A-Z list markup, I have created an area called title-status. This will hold our two features.
- az-template.php
<div id="title-status">
<p>Showing: <span></span></p>
<p id="show-all">Show all posts</p>
</div>
Now we style this area with some CSS
- style.css
#title-status {
float: left;
width: 100%;
}
#title-status p {
float: left;
width: 50%;
margin-bottom: 15px;
font-size: 16px;
}
#title-status span {
font-weight: bold;
text-transform: uppercase;
}
#title-status p:last-child {
text-align: right;
text-decoration: underline;
color: #de466c;
cursor: pointer;
}
And we have this.
![](/wp-content/uploads/2020/05/Create-an-A-Z-Filter-For-WordPress-Posts-7.png)
The very last piece of the puzzle is adding a few more lines of JavaScript.
- main.js
// Let's create 3 new variables
let title_showing = jQuery('#title-status span'); // Create new var to hold what character we are viewing
let az_li = jQuery('#a-z li'); // Create new var to get all A-Z list items
let title_show_all = jQuery('p#show-all'); // Create new var to target the show-all paragraph tag
// Initial load
title_showing.text(initial_first_letter);
// Clicking A-Z list items
jQuery('#a-z li.active').click(function()
{
...
title_showing.text(click_first_char);
title_show_all.show();
});
title_show_all.click(function() // Show all posts function
{
posts_results_li.addClass('show'); // Show all posts
title_showing.text('all'); // Append the word all to our span inside the #title-status paragraph
az_li.removeClass('current'); // Remove current class from all A-Z list items
jQuery(this).hide(); // Hide title_show_all link
});
We now have a nifty interactive filter working now! Have fun with it. Here’s a link to Github to download all of the code used.