Top 3 categories shown in WordPress

On the homepage of Yosora there are 3 percentage circles. Those circles stand for 1 of the top 3 categories on this blog. They calculate dynamically how big the corresponding category is compared to all the posts published here on this site. Since WordPress doesn’t provide this by default I had to write a custom function to make this possible.

Display the top 3 categories by percentage on WordPress

Getting the categories

To be able to calculate the top 3 categories in percentages I needed the category name, the category post count and the total categories post count. So my first stop was wp_list_categories. This is a standard wordpress function that accepts a range of parameters. With this function I managed to get my top 3 categories based on the post count. The problem only with this function is that the output will be in a <ul> list. While I needed an array with seperated values.

Eventually I came across this post where someone needed to alter the layout output of wp_list_categories. It was suggested to him to use get_categories instead of wp_list_categories. And this was exactly what I needed too. The following code will give the same output, with the big difference that this give me full control over the output.

$args=array(
	'orderby' => 'count',
	'order' => 'DESC',
	'show_count' => true,
	'title_li' => '',
	'number' => 6
);

$categories = get_categories($args);

foreach($categories as $category) {

	$output = '<li>';
	$output .= '<img src="img/' . $category->slug . '.jpg" alt="' . $category->name . ' icon" />';
	$output .= '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a>';
	$output =. '</li>';

}

With $args we can control which parameters we pass to the get_categories function. As I needed only the top 3 categories based on post count my parameters became as followed:

$args = array(
	'orderby' => 'count',
	'order' => 'DESC',
	'number' => '3'
	);

The variable $output stores the output of the function. As we generate the output ourselves instead of through the function we have full control over the output and we can alter it the way we want. Within this custom function I get the category name and count. So that is 2 out of 3 needed. Now all I need is the total post count.

Getting the total post count

I am sure there is an easy way in WordPress to get the total post count. Only some of my posts are posted in 2 categories. Therefor I want them to be counted twice instead of once. To get this to work I used the same function. Only this time I wanted all the categories as I wanted to count the total number of post on a per category base. This resulted in the following code:

// get category objects
$counts = get_categories();

// count all categories
foreach($counts as $count) {

	// Increment count the posts for every category
	$total_posts = $total_posts + $count->category_count;

}

With this code I get the total number of posts on a per category base stored in the $total_posts variable. So that is 3 out of 3 needed. The rest is just simple mathematics. Since part (category post count) divided by whole (total numer of posts) times 100 will give us a percentage number. As I only need a whole percentage numbers and no decimal numbers i use the round() function

// Calculate a percentage on whole numbers
$percentage = round( ( $category->category_count / $total_posts ) * 100 );

Show the top 3 categories

Okay, so I have the total number of posts, and I have an array with details of the top 3 categories. Now all I need is a way to make the circles. For this I make use this purely css based stylesheet. I include it in my theme by uploading the circle.css file to /css/ folder in my themes folder and adding the following code to my functions.php:

wp_enqueue_style( 'driving-my-passion-circle', get_template_directory_uri() . '/css/circle.css' );

Now the stylesheet is included I can make it work with the following html code:

<div class="c100 p25 big">
	<span>25%</span>
	<div class="slice">
		<div class="bar"></div>
		<div class="fill"></div>
	</div>
</div>

The final piece of the puzzle is to show the correct percentages. Therefore its useful to understand the above code. As the p25 element will fill the bar and the 25% will display the text. As soon as I integrate this code in the function I can replace the numbers with the $percentage variable. This will make bothe the bar and the text display the correct numbers.

Since I wanted to be able to call this function I decided to wrap it inside a shortcode function. Which made the final code look like this:

// Declare a new function
function yosora_top_category() { 
 
	// First get total amount op post counted by category
	// Get category objects
	$counts = get_categories();

	// Count all categories
	foreach($counts as $count) {

		// Increment count the posts for every category
		$total_posts = $total_posts + $count->category_count;

	}

	// Second get the top 3 categories
	$args = array(
		'orderby' => 'count',
		'order' => 'DESC',
		'number' => '3'
		);

	// Get category objects
	$categories = get_categories($args);

	// Set vars
	$output = '';

	// Loop objects
	foreach($categories as $category) {
		
		//Calculate percentage
		$percentage = round( ( $category->category_count / $total_posts ) * 100 );

		// Build output
		$output .= '<a href="' . get_category_link($category->term_id) . '">';
		$output .= '<div class="c100 p' . $percentage . ' big orange">';
		$output .= '<span>' . $percentage . '%</span>';
		$output .= '<div class="slice"><div class="bar"></div><div class="fill"></div></div></div><h3>' . $category->name . '</h3>';
		$output .= '</a>';

	}
	 
	// Return the output
	return $output;
	} 
// Register the shortcode
add_shortcode('yosora-top-category', 'yosora_top_category'); 

Now I can call this shortcode from within WordPress by using:

[yosora-top-category]

Or I can call it with php in the template by using:

<?php echo do_shortcode("[yosora-top-category]"); ?>
Posted in: Programming
Tags: , , , , , ,

About Remco

Hi, I'm Remco and I'm the founder of Yosora. I'm a self taught web developer and a technology enthusiast with a passion for motorcycles. I have been a web entrepreneur, and since 2018 I'm working as a jr systems administrator. For my day job I administrer Microsoft systems, but in my spare time I still prefer to work with Linux systems.

Leave a Reply

Your email address will not be published. Required fields are marked *