How to Create a Tag Cloud With JavaScript and CSS

Javascript Jan 04, 2021

A tag cloud is a visual depiction of textual data. It uses varying font sizes to convey the importance, priority, significance, weight etc. of the data it represents.

This is a tutorial on how to build a tag cloud with pure JavaScript and CSS.

THE PLAN

Before jumping into the JavaScript and CSS, I think its best to understand what we will be doing.

The only HTML tag we need for making our tag cloud is, <ul>. And to make it unique, we will give it an id with the value "tag-cloud".

<ul class="tag-cloud">

</ul>

We will use JavaScript to populate this tag with the contents from this JSON file. The JSON file contains details like the tag title, the URL, and a list of article titles. Shown below is one entry from the JSON file:

{
    "title": "Fortran",
    "url": "https://example.com/tags/fortran",
    "articles": [
        "Fortran article one",
        "Fortran article two"
    ]
}

We will use AJAX to fetch and process the JSON file. We need to make an <li> entry inside <ul id="tag-cloud"> for each entry in the JSON file and set the proper font size for it depending on the number of articles that particular tag name has. Essentially, we want all our <li> elements to look similar to this,

<li>
    <a href="https://..." style="font-size: 1.1em">
       Fortram [2]
    </a>
</li>

THE JavaScript

First, let's create some variables.

var jsonURL =
    "https://gist.githubusercontent.com/reiri-k/94ea88d5709f32711555c1dd73a62d0f/raw/d0550f4d39d40eac0550922133f983e02915b1da/tags.json"
var ulTag = document.getElementById("tag-cloud")
var minFontSize = 1
var maxFontSize = 2
var liTags = ""
var weights = []

The minFontSize and maxFontSize sets the font size (in em) of the smallest and largest tag in our tag cloud. The liTags variable is for holding all the <li> entries that we will put inside <ul id="tag-cloud">. And finally, the weights variable will hold an array of weights of tags.

Note: The weight of a tag is the number of articles it has. So, the weight of a tag with only 1 article is 1. And the weight of a tag with 12 articles is 12.

THE AJAX REQUEST

We will be using pure JavaScript for our AJAX handling. If you're totally unfamiliar of the old sacred ways, it is recommended that you take your time to read and understand it.

Extra Reading: Ajax without Jquery

var ajax = new XMLHttpRequest()
ajax.open('get', jsonURL)
ajax.addEventListener('load', (e) => {

	// EVERYTHING HAPPENS IN HERE
    
}, false)
ajax.send()

We start by populating the weights array. This variable is needed for calculating the font size later. We can't have duplicate values in it, and it should be sorted in ascending order, from the least to the highest weight.

jsonData = JSON.parse(e.currentTarget.response)

// populating weights
jsonData.forEach((result) => {
    numberOfArticles = result.articles.length
    if (!weights.includes(numberOfArticles)) {
        weights.push(numberOfArticles)
    }
})

// sorting contents of weights in assending order
weights.sort((a, b) => a - b)

Next, we calculate the font size, generate all the <li> elements and stuff them inside <ul class="tag-clouds>. We calculate the font size by normalizing the weights of the tags and then scaling them to values between minFontSize (1em) and maxFontSize (2em).

// generating <li> tags and putting them in 'liTags'
jsonData.forEach((result) => {
    title = result.title
    url = result.url
    numberOfArticles = result.articles.length
    m = weights.indexOf(numberOfArticles) + 1
    a = ((m - weights[0]) / (weights.length - weights[0]))
    b = (maxFontSize - minFontSize)
    c = minFontSize
    font_size = a * b + c
    liTags = liTags.concat(
        `<li>
            <a href="${url}" style="font-size: ${font_size}em;">
                ${title} [${numberOfArticles}]
            </a>
        </li>`
    )
}) /* end of jsondata.forEach() */

// inserting generated <li> tags into <ul>
ulTag.innerHTML = liTags

If anyone is curious about the formula used to get the font size:

$$ \frac{w-w_{\text{min}}}{w_{\text{max}}-w_{\text{min}}}\times (t_{\text{max}}-t_{\text{min}}) + t_{\text{min}} $$

Now, the complete AJAX request would look like this,

var ajax = new XMLHttpRequest()
ajax.open('get', jsonURL)
ajax.addEventListener('load', (e) => {

    jsonData = JSON.parse(e.currentTarget.response)

    // populating weights
    jsonData.forEach((result) => {
        numberOfArticles = result.articles.length
        if (!weights.includes(numberOfArticles)) {
            weights.push(numberOfArticles)
        }
    })

    // sorting contents of weights in assending order
    weights.sort((a, b) => a - b)

    // generating <li> tags and putting them in 'liTags'
    jsonData.forEach((result) => {
        title = result.title
        url = result.url
        numberOfArticles = result.articles.length
        m = weights.indexOf(numberOfArticles) + 1
        a = ((m - weights[0]) / (weights.length - weights[0]))
        b = (maxFontSize - minFontSize)
        c = minFontSize
        font_size = a * b + c
        liTags = liTags.concat(
            `<li>
                <a href="${url}" style="font-size: ${font_size}em;">
                    ${title} [${numberOfArticles}]
                </a>
            </li>`
        )
    }) /* end of jsondata.forEach() */

    // inserting generated <li> tags into <ul>
    ulTag.innerHTML = liTags
}, false)
ajax.send()

THE CSS

As for the CSS, for giving you more freedom to experiment with, I will keep it nice and clean with nothing unnecessary.

#tag-cloud {
    display: block;
}

#tag-cloud li {
    display: inline-block;
    padding-right: 20px;
}

#tag-cloud li:nth-last-child(1) {
    padding-right: 0px;
}

#tag-cloud li a {
    text-decoration: none;
    color: grey;
}

#tag-cloud li a:hover {
    color: black;
}

FINAL RESULT

Here is a preview of what we have created. If you like it, use JSfiddle to fiddle around with the source code. Experiment and learn new things!

That is all! Creating a simple and functional tag cloud from scratch with pure JavaScript and CSS is this simple and easy.

Tags

Lime

Simple, like quantum physics.