BAC Software Consulting Blog

How To Customize WordPress Tag Cloud Without a Plugin

For a WordPress blog, a Tag cloud displays a list of tags. Tags are usually single words, and the importance of each Tag is shown with different font size. The size of each Tag is determined by how many times that particular Tag has been assigned to posts. Tags are links that lead to a list of posts associated with each Tag. The WordPress Tag cloud is a widget that displays all popular tags in a convenient layout.

Tag Cloud Benefits

Like any WordPress Widget, and depending on the flexibility of your theme, Tag cloud widget can be used anywhere in your WordPress Website. Your readers can search different topics based on Tags instead of categories. Also Tags help your Website gain higher ranking in Search Engines by using different keywords related to the post. Tags are text links, rich in keywords, that are indexed by search engines. A Tag cloud would help your Website with more search queries. The more you use the same tags, the more they will grow in importance for your visitors and search engines. It is important to keep tags relevant to the post. Around 5 tags per post is good enough.

Default WordPress Tag Cloud

If you are using the standard version of the WordPress Tag cloud, you may dislike how it looks. Many people, including myself, are not happy with just using the default WordPress Tag Cloud widget without being able to modify it. We want to have control. This is where this tutorial helps!

Custom Tag Cloud

My version of the Tag cloud lets you customize it to your liking. Also in my code you have additional controls that are not part of the default WordPress Tag cloud. The custom Tag cloud on the right sidebar of this blog is generated by the code shown below.

Prerequisite: This tutorial assumes that your WordPress theme already supports widgets. To find out, check your theme´s documentation. Also it should be mentioned in your WordPress dashboard. Your theme must support widgets, for this code to work.

What about a Plugin? Yes, there are plugins that customize WordPress Tag Clouds, but haven´t you read my previous post about the disadvantages of going crazy adding plugins to your theme?

Advantages of My Custom Tag Cloud Code

These are the main advantages of adding my code:

  1. No need to install an additional plugin for your WordPress Website.
  2. The code is added to your theme´s functions.php file. Your WordPress core files are not modified.
  3. You can change any default parameter to your liking: (smallest, largest, unit, number, format, separator, order, etc).
  4. In addition: My custom Tag cloud code allows you to:
    • Limit the Tags in the cloud based on their weight (i.e. number of posts they are attached to). For example, you can exclude tags that have more than or less than some defined number of posts.
    • Change The Tag color based on its weight. The Tag weight is determined by the number of posts attached to each Tag. For example, Tags with less weight will have a different color than Tags with more weight.

WordPress Custom Tag Cloud Code

This is my version of the custom Tag cloud code. Open the functions.php file located in your theme´s folder and add (copy and paste) the following three functions. This code is tested to work for the current WordPress version. Sorry for the long code!
Note: If the vertical scroll bar is shown, you need to scroll all the way down to see the horizontal bar.

     To set your own parameters, search the code for: ***MODIFY TO WHAT YOU LIKE*** 
<?php
/***** Custom Tag Cloud Code without the need of a Plugin. 
       Tested up to WordPress version 3.1.2 *****/
 
/** Function that generates Tag colors based on their weight (number of posts per Tag)
If nothing gets passed in to the function for $min_color and $max_color, it skips the function
and uses the defined link color in the CSS.  If only one color is passed, it is used for both.
Function is based on Version 5.2 of the Configurable Tag Cloud plugin **/
 
function color_weight($weight, $min_color, $max_color) {
    if ($min_color == "" && $max_color == "")
        return;
 
    if ($min_color == "") {
        $color = $max_color;
        return $color;
    }
    if ($max_color == "") {
        $color = $min_color;
        return $color;
    }
    if ($weight) {
        $weight = $weight/100;
 
        //hack to handle CSS shorthand color definitions (i.e., #000 instead of #000000)
        //strlen — Get string length (http://php.net/manual/en/function.strlen.php)
        if (strlen($min_color) == 4) {
            //substr — Return part of a string (http://php.net/manual/en/function.substr.php)
            $r = substr($min_color, 1, 1);
            $g = substr($min_color, 2, 1);
            $b = substr($min_color, 3, 1);
 
            $min_color = "#$r$r$g$g$b$b";
        }
        if (strlen($max_color) == 4) {
            $r = substr($max_color, 1, 1);
            $g = substr($max_color, 2, 1);
            $b = substr($max_color, 3, 1);
 
            $max_color = "#$r$r$g$g$b$b";
        }
        //hexdec — Hexadecimal to decimal (http://php.net/manual/en/function.hexdec.php)
        $minr = hexdec(substr($min_color, 1, 2));
        $ming = hexdec(substr($min_color, 3, 2));
        $minb = hexdec(substr($min_color, 5, 2));
 
        $maxr = hexdec(substr($max_color, 1, 2));
        $maxg = hexdec(substr($max_color, 3, 2));
        $maxb = hexdec(substr($max_color, 5, 2));
 
        //intval — Get the integer value (http://php.net/manual/en/function.intval.php)
        $r = dechex(intval((($maxr - $minr) * $weight) + $minr));
        $g = dechex(intval((($maxg - $ming) * $weight) + $ming));
        $b = dechex(intval((($maxb - $minb) * $weight) + $minb));
 
        if (strlen($r) == 1) $r = "0".$r;
        if (strlen($g) == 1) $g = "0".$g;
        if (strlen($b) == 1) $b = "0".$b;
 
        $color = "#$r$g$b";
        $color = substr($color,0,7);
         
        return $color;
    }
}
 
/*** Function that Generates an HTML string that makes the Tag Cloud ****/
//See Reference: http://codex.wordpress.org/Template_Tags/wp_generate_tag_cloud
//This function is similar as 'wp_generate_tag_cloud()' located in: 'wp-includes/category-template.php'
//Major difference: This function COLORS the Tags in the cloud based on their 
//weight (number of posts attached to the Tag) as shown in the short code. 
  
function bac_generate_tag_cloud( $tags, $args = '' ) {
    global $wp_rewrite;
    $defaults = array( //***KEEP THE DEFAULTS DON'T TOUCH.***
        'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0,
        'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC',
        'topic_count_text_callback' => 'default_topic_count_text',
        'topic_count_scale_callback' => 'default_topic_count_scale', 'filter' => 1,
    );
    //!isset — Determine if a variable is NOT set or is NULL (http://php.net/manual/en/function.isset.php)
    if ( !isset( $args['topic_count_text_callback'] ) && isset( $args['single_text'] ) && isset( $args['multiple_text'] ) ) {
        //var_export — returns a parsable string representation of a variable (http://php.net/manual/en/function.var-export.php)
        $body = 'return sprintf (
            _n(' . var_export($args['single_text'], true) . ', ' . var_export($args['multiple_text'], true) . ', $count),
            number_format_i18n( $count ));';
        //create_function — Create an anonymousfunction (http://php.net/manual/en/function.create-function.php)
        $args['topic_count_text_callback'] = create_function('$count', $body);
    }
    $args = wp_parse_args( $args, $defaults );
    //extract — Import variables into the current symbol table from an array (http://php.net/manual/en/function.extract.php)
    extract( $args );
 
    if ( empty( $tags ) )
        return;
 
    $tags_sorted = apply_filters( 'tag_cloud_sort', $tags, $args );
    if ( $tags_sorted != $tags  ) { // the tags have been sorted by a plugin
        $tags = $tags_sorted;
        unset($tags_sorted);
    } else {
        if ( 'RAND' == $order ) {
            shuffle($tags);
        } else {
            // SQL cannot save you; this is a second (potentially different) sort on a subset of data.
            if ( 'name' == $orderby )
                uasort( $tags, create_function('$a, $b', 'return strnatcasecmp($a->name, $b->name);') );
            else
                uasort( $tags, create_function('$a, $b', 'return ($a->count > $b->count);') );
 
            if ( 'DESC' == $order )
                $tags = array_reverse( $tags, true );
        }
    }
    if ( $number > 0 )
        $tags = array_slice($tags, 0, $number);
 
    $counts = array();
    $real_counts = array(); // For the alt Tag
    foreach ( (array) $tags as $key => $tag ) {
        $real_counts[ $key ] = $tag->count;
        $counts[ $key ] = $topic_count_scale_callback($tag->count);
    }
    $min_count = min( $counts );
    $spread = max( $counts ) - $min_count;
    if ( $spread <= 0 )
        $spread = 1;
    $font_spread = $largest - $smallest;
    if ( $font_spread < 0 )
        $font_spread = 1;
    $font_step = $font_spread / $spread;
 
    $a = array();
 
    foreach ( $tags as $key => $tag ) {
        $count = $counts[ $key ];
        $real_count = $real_counts[ $key ];
        $tag_link = '#' != $tag->link ? esc_url( $tag->link ) : '#';
        $tag_id = isset($tags[ $key ]->id) ? $tags[ $key ]->id : $key;
        $tag_name = $tags[ $key ]->name;
         
        /* Short code that changes the Tag color based on its weight (how many posts are attached to each Tag.) */
        //Define Variable: Beginning color for Tag. format" "#xxx" or "#xxxxxx" where x = [0-9,a-f]
        //If both variables are not defined it uses the Tag color as defined in the CSS document.
        $min_color = "#5679B9"; //***MODIFY TO WHAT YOU LIKE***
          
        //Define Variable: Ending color for Tag. format" "#xxx or "#xxxxxx"
        $max_color = "#AF1410"; //***MODIFY TO WHAT YOU LIKE***
         
        if ($largest == $smallest)
            $tag_weight = $largest;
        else
            $tag_weight = ($smallest+(($count-$min_count)*$font_step));
             
        $diff = $largest-$smallest;
         
        if ($diff <= 0)
            $diff = 1;
        //round — Rounds a float (http://php.net/manual/en/function.round.php)  
        $color_weight = round(99*($tag_weight-$smallest)/($diff)+1);
         
        //this is the color_weight() functions defined above. 
        $tag_color = color_weight($color_weight, $min_color, $max_color);
                 
        //Modified to include Tag Link color.
        //call_user_func — Call a user function given by the first parameter (http://php.net/manual/en/function.call-user-func.php) 
        $a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . esc_attr( call_user_func( $topic_count_text_callback, $real_count ) ) . "' style='font-size: " . 
            ( $smallest + ( ( $count - $min_count ) * $font_step ) )
            . "$unit;  color: $tag_color; background-color: inherit;'>$tag_name</a>"; //background-color is added for validation purposes.
        /*** End of short code ***/     
    }   
    switch ( $format ) :
    case 'array' :
        $return =& $a;
        break;
    case 'list' :
        $return = "<ul class='wp-tag-cloud'>\n\t<li>";
        //join — Alias of implode() (http://php.net/manual/en/function.join.php)
        $return .= join( "</li>\n\t<li>", $a );
        $return .= "</li>\n</ul>\n";
        break;
    default :
        $return = join( $separator, $a );
        break;
    endswitch;
         
        //Function to create a new filter hook (http://codex.wordpress.org/Function_Reference/apply_filters)
        return apply_filters( 'bac_generate_tag_cloud', $return, $tags, $args );
}
 
/*** Function that Displays the Tag Cloud ****/
//See Reference: http://codex.wordpress.org/Template_Tags/wp_tag_cloud 
//This function is similar as 'wp_tag_cloud()' located in: 'wp-includes/category-template.php'
//Major difference: This function excludes Tags in the cloud based on their weight as shown in the short code. 
function bac_tag_cloud($args) {
 
$defaults = array( // ***MODIFY TO WHAT YOU LIKE***
 
    'smallest' => 12,   //The smallest Tag (lowest count) is shown at size 12
    'largest' => 30,    //The largest Tag (highest count) is shown at size 30 
    'unit' => 'px',     //Unit of measure for the smallest and largest values. Can be any CSS value (pt, px, em, %). 
    'number' => 50,     //set how many tags to show (default is 45 tags in the Tag cloud list).
    'format' => 'flat', // Format of the cloud display (flat, list, array) 
    'separator' => "\n", //The text/space between tags. 
    'orderby' => 'name', //argument will accept 'name' or 'count' and defaults to 'name'.
    'order' => 'ASC',   //sort order, defaults to 'ASC' and can be 'DESC'
    'exclude' => '',   //Exclude a specific Tag by its Tag ID separated by commas.
    'include' =>'',   //Include a specific Tag by Tag ID separated by commas. Use 'exclude' or 'include', but not both.
    'link' => 'view',  //Set link to allow edit of a particular Tag.
    'taxonomy' => 'post_tag', //Taxonomy or array of taxonomies to use in generating the cloud. 
    'echo' => true //DO NOT TOUCH THIS.
); //***End Of MODIFY SECTION***
 
//wp_parse_args() is a generic utility for merging together an array of arguments and an array of default values. 
/*http://codex.wordpress.org/Function_Reference/wp_parse_args*/
$args = wp_parse_args( $args, $defaults );
//Retrieve the terms in taxonomy or list of taxonomies. 
/*http://codex.wordpress.org/Function_Reference/get_terms  ;    http://php.net/manual/en/function.array-merge.php*/
// Always query top tags
$tags = get_terms( $args['taxonomy'], array_merge( $args, array( 'orderby' => 'count', 'order' => 'DESC' ) ) ); 
 
//If there are no tags
if ( empty( $tags ))
    return; //ends execution of the current function
 
/***** Short Code that gives the user the option not to display Tags in the Cloud 
based on the Tag's weight (number of posts attached to the Tag.)  *****/
 
//Minimum number of posts per tags. ***MODIFY TO WHAT YOU LIKE***
$min_num = 1;  // Tags with less than this number of posts will not be displayed.
 
//maximum number of posts per tags. ***MODIFY TO WHAT YOU LIKE***
$max_num = 65; //Tags with more than this number of posts will not be displayed.
 
foreach($tags as $key => $tag)
    {   //If the post count of Tag is outside the range
        if($tag->count < $min_num || $tag->count > $max_num)
        {
            /*unset()-destroy a single element of an array - http://php.net/manual/en/function.unset.php*/
            unset($tags[$key]);
        }
    }
/*** End of short code ***/
 
foreach ( $tags as $key => $tag ) {
        if ( 'edit' == $args['link'] )
         
            //Displays a link to edit the current Tag, if the user is logged in and allowed to edit the Tag.
            /*http://codex.wordpress.org/Function_Reference/edit_tag_link*/
            $link = get_edit_tag_link( $tag -> term_id, $args['taxonomy'] );
        else
            //Returns permalink for a taxonomy term archive. 
            /*http://codex.wordpress.org/Function_Reference/get_term_link*/
            $link = get_term_link( intval($tag -> term_id), $args['taxonomy'] );
         
        //Check whether variable is a WordPress Error. 
        /*http://codex.wordpress.org/Function_Reference/is_wp_error*/
        if ( is_wp_error( $link ) )
            return false;
 
    $tags[ $key ] -> link = $link;
    $tags[ $key ] -> id = $tag -> term_id;
}
//Generates a Tag cloud (heatmap) from provided data. Located at: 
$return = bac_generate_tag_cloud( $tags, $args ); // Here is where those top tags get sorted according to $args
 
//Function to create a new filter hook.
/*http://codex.wordpress.org/Function_Reference/apply_filters*/
$return = apply_filters( 'bac_tag_cloud', $return, $args );
 
if ( 'array' == $args['format'] || empty($args['echo']) )
    return $return;
 
echo $return;
}
//Hooks a function to a specific filter action.
/*http://codex.wordpress.org/Function_Reference/add_filter*/
add_filter('wp_tag_cloud', 'bac_tag_cloud');
?>

Styling the Custom Tag Cloud

Finally we need to style the custom Tag cloud code with CSS. The following CSS code is what I used for this blog. The code should be part of your theme´s CSS file (usually called style.css). You probably already have a CSS code in place for the cloud and this step might not be necessary.

/* Styling Custom Tag Cloud Widget */
 
#sidebar ul li.widget_tag_cloud{
    padding:0 0 30px 0; 
}
#sidebar ul li.widget_tag_cloud a{
    background-color:inherit;
    text-decoration:none;   
    padding:0 0 0 15px;
    line-height:22px;
    color:#DF8D0D;
}
#sidebar ul li.widget_tag_cloud a:hover{
    text-decoration: none;
    color:#695321 !important; 
    background-color: inherit;
}

Conclusion

You now can customize your Tag cloud without the need of a plugin and without modifying your WordPress core files. In addition, you have more control of what tags to show and what color to display based on their weight.

A Comprehensive Guide on Creating Typography Effects Using jQuery and CSS3

Overlooking typography is perhaps something you might have been running away from, all through your career of building remarkable websites. Right from paying attention to multiple website assets such as logo design, navigational structure and tone to working out the addition of special typographical effects; you might have put in your best efforts for building a website with a rich look and feel.

What is covered in this tutorial?

This tutorial is dedicated to all those who are inclined on gathering details about different ways of enhancing the typography as well as the ones who are getting awakened about the pros of including typography effects in their web design. Here, I will be explaining you the use of CSS3 and jQuery for creating specific typographic effects for a big headline.

The HTML

We will be using an underline structure which is basically a div element containing an anchor. Here is the container which wraps the headline:

<div id="typography" class="typography">
  <a href="#">Typography</a>
</div>

After this, we will be exploring the different styling options available for the headline.

Before moving forward, here is a glimpse of CSS3 Keyframe animations

The CSS3 Keyframe animations method is employed for creating animations by introducing a change between individual CSS styles. That means, as you animate using CSS keyframes, you can opt for manipulating the CSS styles as well. If you intend to generate fluid animations (the ones which don’t require extensive scripting) then CSS keyframe is for you.

The @keyframe rule

As an integral part of the CSS keyframes concept, @keyframe is a CSS rule the reference for which can be found in other CSS sections. This rule is followed by multiple CSS rules which are defined using curly braces.

A typical @rule is similar to this:

@keyframes frameEffect{
    /* rule sets go here … */
}

Knowing about the Keyframe Selectors

Keyframe Selectors come with their unique set of rules and values. Here’s a look at how you can define them:

@keyframes frameEffect{
   0% { ... }
 
   30% { ... }
 
   55% { ... }
 
   100% { ... }
}

As suggested by the above code, when the animation starts, the level is displayed as 0% and when it finishes off, the level scales to 100%. The intermediate levels are prepresented as 30% and 55%. Note that the different levels denote the different states of the animation in terms of appearance as well.

With each part of the keyframe, you can see different values that can be utilized for performing simple tweaks. For example, you may use the z-index for stacking the elements. Plus, you may even add the below code snippet for defining a name for the animation:

.typography a span:hover {
     animation-name: frameEffect;
}

If you look at the above code, you will find that that I have added an animation-name property which has a value that is in synchronization with the identifier available with the @keyframe rule. Here, you may even set the value of animation-name property to ‘none’ with the help of Javascript. Additionally, there are two property values viz: animationname which defines the name of animation and keyframe-selector which determines the percentage of animation duration.

Lettering.js

For my example, I will be using lettering.js which serves for styling the single letters of the words that need to go into the headline. There are situations when you might find it convenient to use .char# pattern for monitoring the text available in the CSS. This would allow you to change specific text pieces instantly.

Currently CSS does not offer complete down-to-the-letter control. So this is where the Lettering.js jQuery plugin give you that control.

Here is the complete code for implementing everything that has been covered in the above paragraghs:

The HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Special Typography Effects Using jQuery and CSS3</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="typography" class="typography">
  <a href="#">Typography</a>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.lettering.js"></script>
</body>
</html>

The CSS

Below, is the CSS code that I used for this demo.

.typography {
padding: 10px;
margin: 10px auto;
text-align: center;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
}
.typography a {
text-align: center;
padding: 10px;
text-decoration: none;
}
.typography a span {
font-size: 102px;
color: #7f7f7f;
 opacity: 1;
 display: inline-block;
 text-shadow: 0px 0px 2px #444, 1px 1px 4px rgba(0,0,0,0.7);
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
transition: all 0.5s linear;
}
.typography a span:hover{
color: #000;
-webkit-animation: frameEffect 0.6s linear infinite forwards ;
-moz-animation: frameEffect 0.6s linear infinite forwards ;
-ms-animation: frameEffect 0.6s linear infinite forwards ;
animation: frameEffect 0.6s linear infinite forwards ;
}
/* Standard syntax */
@keyframes frameEffect {
 0% { transform: scale(1.2);  }
 25% { transform: scale(1.4);  }
 55% { transform: scale(1.6);  }
 85% { transform: scale(1.3); }
 100% {  transform: scale(1); }
}
/* Mozilla Firefox */
@-moz-keyframes frameEffect {
  0% { -moz-transform: scale(1.2);  }
 25% { -moz-transform: scale(1.4); }
 505 { -moz-transform: scale(1.6); }
 85% { -moz-transform: scale(1.3);  }
 100% {  -moz-transform: scale(1); }
}
/* Chrome, Safari, Opera */
@-webkit-keyframes frameEffect {
  0% { -webkit-transform: scale(1.2); }
 25% { -webkit-transform: scale(1.4);  }
 55% { -webkit-transform: scale(1.6);  }
 85% { -webkit-transform: scale(1.3);  }
 100% { transform: scale(1); }
}
/* IE9 and older */
@-ms-keyframes frameEffect {
   0% { -ms-transform: scale(1.2); }
 25% { -ms-transform: scale(1.4); }
 55% { -ms-transform: scale(1.6); }
 85% { -ms-transform: scale(1.3); }
 100% { -ms-transform: scale(1); }
}

JavaScript Block With the .lettering() method

Add the code below at the end of the HTML document just before the closed body tag (</body>)

<!-- script block with the magical .lettering() method. -->
<script type="text/javascript">
$(document).ready(function()  {
  $("#typography a").lettering(); 
  //You could also call it by class name:  $(".typography a").lettering();
});
</script>

What’s your opinion about this tutorial?