Back to Writing

Animated jQuery Bar Chart Tutorial

Learn how to build a dynamic, animated bar chart using jQuery, HTML, and CSS from scratch.

Eli Geske 15 min read
jquery data-visualization animation javascript css

Since everyone was digging the Star Comment Rating, I decided to share this animated jQuery Bar Chart too. I’ve been holding onto it for a while, and now it’s yours for the taking.

Animated jQuery Bar Chart Tutorial

Overview

This bar chart is built using basic HTML, CSS, and jQuery. To make it easier to follow, the logic is broken down into functions and uses a JavaScript Object to hold all the necessary parameters.

The chart grows and stretches based on the height and width you set in your CSS, but there’s a catch: to keep it looking clean, the height and width should be divisible by certain values (which we’ll cover below).

The Preview

Here is the animated jQuery Bar Chart we will be making:

Animated jQuery Bar Chart Preview

The HTML Structure

We use a table to house both the chart and its legend. The first cell contains the chart container, and the second cell contains the values that the chart will pull from.

<table id="testgraph" class="graphtable">
  <tr>
    <td>
      <div class="gCont">
        <div class="graph"></div>
      </div>
    </td>
    <td class="values">
      <label
        >First Number:<span style="background-color: #06F;">34</span></label
      >
      <label
        >Second Number:<span style="background-color: #C60;">20</span></label
      >
      <label
        >Third Number:<span style="background-color: #936;">15</span></label
      >
      <label
        >Fourth Number:<span style="background-color: #96C;">30</span></label
      >
      <label
        >Fifth Number:<span style="background-color: #396;">18</span></label
      >
    </td>
  </tr>
</table>
  • .gCont: The Graph Container.
  • .graph: Where the lines and numbers will be placed via jQuery.
  • .values: Contains <label> elements for each bar. The <span> holds the actual value and the background color for that bar.

The CSS

The key to the layout is setting a specific height and width for the graph.

#testgraph .graph {
  height: 170px; /* Should be divisible by the number of graph lines */
  width: 300px; /* Should be divisible by the number of bars for centering */
}

.graphtable td {
  vertical-align: top;
  font-family: Arial, Helvetica, sans-serif;
}
.graphtable label {
  display: block;
  width: 145px;
  height: 25px;
  font-size: 13px;
  padding-left: 35px;
}
.graphtable label span {
  display: block;
  width: 55px;
  float: right;
  height: 15px;
  width: 15px;
  border: 1px solid #ccc;
  text-indent: -20px;
}
.line {
  font-size: 10px;
}
.graph {
  margin-left: 35px;
  border: 1px solid #666;
}
.graph .line {
  border-bottom: 1px solid #ccc;
  margin-top: -1px;
}
.graph .fix {
  border-bottom: none;
}
.graph .line span {
  position: absolute;
  display: block;
  margin-left: -40px;
  width: 35px;
  text-align: right;
  margin-top: -5px;
}
.bar {
  position: absolute;
  margin-bottom: 0;
}

The jQuery Logic

We use a configuration object $v to store all the graph’s parameters and state.

1. Initialization: graphit()

This function sets up our graph object and triggers the subsequent steps.

function graphit($graph_id, $lines, $bar_margins, $bar_speed, $animate) {
  $v = new Object()
  $v.graphid = $graph_id
  $v.values = new Array()
  $v.heights = new Array()
  $v.colors = new Array()
  $v.lines = $lines
  $v.bm = $bar_margins
  $v.mx = 0
  $v.gw = $('#' + $v.graphid + ' .graph').width()
  $v.gh = $('#' + $v.graphid + ' .graph').height()
  $v.speed = $bar_speed
  $v.animate = $animate

  getValues() // Load values & colors
  graphLines() // Draw the scale lines
  graphBars() // Create the bars
  if ($v.animate) animateBars(0) // Animate if enabled
}

2. Loading Values: getValues()

We loop through the legend’s <span> elements to extract values and colors.

function getValues() {
  $lbls = $('#' + $v.graphid + ' .values span')
  for ($i = 0; $i <= $lbls.length - 1; $i++) {
    $vals = parseFloat($lbls.eq($i).text())
    $v.colors.push($lbls.eq($i).css('background-color'))
    $v.mx = $vals > $v.mx ? $vals : $v.mx
    $v.values.push($vals)
  }
}

3. Drawing Lines: graphLines()

This handles the math for the scale and draws the horizontal grid lines.

function graphLines() {
  $r = $v.mx < 100 ? 10 : 100
  $v.mx = roundUp($v.mx, $r)
  $d = $v.mx / $v.lines

  $html = ''
  $i = $v.mx
  if ($i > 0 && $d > 0) {
    while ($i >= 0) {
      $html += graphLinesHelper($i, $v.mx)
      $i = $i - $d
    }
  }
  $('#' + $v.graphid + ' .graph').html($html)
  $margin = $v.gh / $v.lines
  $('#' + $v.graphid + ' .line').css('margin-bottom', $margin + 'px')
}

4. Creating Bars: graphBars()

This calculates the width and height of each bar based on the container size and its value.

function graphBars() {
  $xbars = $v.values.length
  $barW = ($v.gw - $xbars * $v.bm) / $xbars
  $mL = $('#' + $v.graphid + ' .line span').width() + $v.bm / 2
  $html = ''
  for ($i = 1; $i <= $xbars; $i++) {
    $v.heights.push(($v.gh / $v.mx) * $v.values[$i - 1])
    $ht = $v.animate == true ? 0 : $v.heights[$i - 1]
    $html +=
      "<div class='bar' id='" +
      $v.graphid +
      '_bar_' +
      ($i - 1) +
      "' style='height: " +
      $ht +
      'px; margin-top: -' +
      ($ht + 1) +
      'px; '
    $html +=
      'background-color: ' +
      $v.colors[$i - 1] +
      '; margin-left: ' +
      $mL +
      "px'>&nbsp;</div>"
    $mL = $mL + $barW + $v.bm
  }
  $($html).insertAfter('#' + $v.graphid + ' .graph')
  $('#' + $v.graphid + ' .bar').css('width', $barW + 'px')
}

5. Animation: animateBars()

Using jQuery’s .animate() to grow each bar sequentially.

function animateBars($i) {
  if ($i == $v.values.length) {
    return
  }
  $('#' + $v.graphid + '_bar_' + $i).animate(
    {
      marginTop: '-' + ($v.heights[$i] + 1) + 'px',
      height: $v.heights[$i] + 'px',
    },
    $v.speed,
    'swing',
    function () {
      animateBars($i + 1)
    },
  )
}

Legacy Archive

[The original post as it appeared on eligeske.com in 2011]

Greetings All! Since everyone was digging the Star Comment Rating I decided that I would give this animated jQuery Bar Chart out too. I’ve been holding onto it for a while, it is now yours for the taking.

This tutorial is a little lengthy, so if you need to get a coffee or use the restroom, we’ll wait.

Your back, good. Here is the Animated jQuery Bar Chart that we will be making.

Not too long ago I had a client dashboard that was in need of a bar chart. Of course there are many plugins out there for javascript charts and even flash. Since I like to know how things work before I stick them on a site I decided to make my animated bar chart from jQuery. The nice thing about this one is that it uses only:

  • Basic HTML
  • CSS
  • Javascript & jQuery

To make it easier for tutorials purposes I broke the javascript down into functions and use a JavaScript Object to hold all of the necessary parameters for making the chart. If you’re new to objects don’t worry it is pretty easy.

For this tutorial, all we need is one HTML document and the latest jQuery called into the page in the <head> tag. I’m using version 1.4.2.

Once you have the above we are going to move onto a quick run down of javascript objects and why I am using them for this tutorial. You ready?

JavaScript Objects: By Reference or By Value

When using a normal variable such as a string or a int(aka number) these are used by Value. Meaning, when you have a variable, let’s say $x just for example purposes, and we say, $x = 0. But then we create a function named — exampleFunction(){ $x=2 } and put $x inside of it and assign it the value of 2.

The first $x still stays 0 because it is outside of that scope. Meaning it uses two separate spaces in memory for this. When using arrays or objects in JavaScript it is by Reference. Meaning it uses one space in memory for that name.

Quick Example: $myarray = new Array('1','2','3'); then we have a function –exampleFunction(){ $myArray – still equals what it was outside of the funciton }.

Now it is the same for objects, but objects have properties which helps organize things. $v = new Object(); $v always stays there in the life of that page until you delete it, save over it, or refresh the page. Got it?

Full Source Code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Eli Geske's Bar Chart</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <style type="text/css">
      /* Graph 1 */
      #testgraph .graph {
        height: 170px; /* Needs to be divisible by Number of Graph lines */
        width: 300px; /* Needs to be divisible by number of Bars */
      }

      .graphtable td {
        vertical-align: top;
        font-family: Arial, Helvetica, sans-serif;
      }
      .graphtable label {
        display: block;
        width: 145px;
        height: 25px;
        font-size: 13px;
        padding-left: 35px;
      }
      .graphtable label span {
        display: block;
        width: 55px;
        float: right;
        height: 15px;
        width: 15px;
        border: 1px solid #ccc;
        text-indent: -20px;
      }
      .line {
        font-size: 10px;
      }
      .graph {
        margin-left: 35px;
        border: 1px solid #666;
      }
      .graph .line {
        border-bottom: 1px solid #ccc;
        margin-top: -1px;
      }
      .graph .fix {
        border-bottom: none;
      }

      .graph .line span {
        position: absolute;
        display: block;
        margin-left: -40px;
        width: 35px;
        text-align: right;
        margin-top: -5px;
      }
      .bar {
        position: absolute;
        margin-bottom: 0;
      }
    </style>
    <script type="text/javascript">
      /**
       * Initiates Graph Functions
       **/
      function graphit($graph_id, $lines, $bar_margins, $bar_speed, $animate) {
        $v = new Object() // create graph object
        $v.graphid = $graph_id // id of graph container, example "graph1" or "myGraph"
        $v.values = new Array() // array of values
        $v.heights = new Array() // array of bar heights
        $v.colors = new Array() // colors for bars
        $v.lines = $lines // number of lines - keep this 10 unless you want to write a bunch more code
        $v.bm = $bar_margins // margins between the bars
        $v.mx = 0 // highest number, or rounded up number
        $v.gw = $('#' + $v.graphid + ' .graph').width() // graph width
        $v.gh = $('#' + $v.graphid + ' .graph').height() // graph height
        $v.speed = $bar_speed // speed for bar animation in milliseconds
        $v.animate = $animate // determines if animation on bars are run, set to FALSE if multiple charts

        getValues() // load the values & colors for bars into $v object
        graphLines() // makes the lines for the chart
        graphBars() // make the bars
        if ($v.animate) animateBars(0) // animate and show the bars
      }

      /**
       * Makes the HTML for the lines on the chart, and places them into the page.
       **/
      function graphLines() {
        $r = $v.mx < 100 ? 10 : 100 // determine to round up to 10 or 100
        $v.mx = roundUp($v.mx, $r) // round up to get the max number for lines on chart
        $d = $v.mx / $v.lines // determines the increment for the chart line numbers

        // Loop through and create the html for the divs that will make up the lines & numbers
        $html = ''
        $i = $v.mx
        if ($i > 0 && $d > 0) {
          while ($i >= 0) {
            $html += graphLinesHelper($i, $v.mx)
            $i = $i - $d
          }
        }
        $('#' + $v.graphid + ' .graph').html($html) // Put the lines into the html
        $margin = $v.gh / $v.lines // Determine the margin size for line spacing
        $('#' + $v.graphid + ' .line').css('margin-bottom', $margin + 'px') // Add the margins to the lines
      }

      /**
       * Creates the html for the graph lines and numbers
       **/
      function graphLinesHelper($num, $maxNum) {
        $fix = $i == $maxNum || $i == 0 ? 'fix ' : '' // adds class .fix, which removes the "border" for top and bottom lines
        return "<div class='" + $fix + "line'><span>" + $num + '</span></div>'
      }

      /**
       * A Simple Round Up Function
       **/
      function roundUp($n, $r) {
        return $n % $r > 0 ? $n - ($n % $r) + $r : $n
      }

      /**
       * Gets the values & colors from the HTML <labels> and saves them into $v ohject
       **/
      function getValues() {
        $lbls = $('#' + $v.graphid + ' .values span') // assigns the span DOM object to be looped through
        // loop through
        for ($i = 0; $i <= $lbls.length - 1; $i++) {
          $vals = parseFloat($lbls.eq($i).text())
          $v.colors.push($lbls.eq($i).css('background-color'))
          $v.mx = $vals > $v.mx ? $vals : $v.mx
          $v.values.push($vals)
        }
      }

      /**
       * Creates the HTML for the Bars, adds colors, widths, and margins for proper spacing.
       * Then Puts it on the page.
       **/
      function graphBars() {
        $xbars = $v.values.length // number of bars
        $barW = ($v.gw - $xbars * $v.bm) / $xbars
        $mL = $('#' + $v.graphid + ' .line span').width() + $v.bm / 2
        $html = ''
        for ($i = 1; $i <= $xbars; $i++) {
          $v.heights.push(($v.gh / $v.mx) * $v.values[$i - 1])
          $ht = $v.animate == true ? 0 : $v.heights[$i - 1]
          $html +=
            "<div class='bar' id='" +
            $v.graphid +
            '_bar_' +
            ($i - 1) +
            "' style='height: " +
            $ht +
            'px; margin-top: -' +
            ($ht + 1) +
            'px; '
          $html +=
            'background-color: ' +
            $v.colors[$i - 1] +
            '; margin-left: ' +
            $mL +
            "px'>&nbsp;</div>"
          $mL = $mL + $barW + $v.bm
        }
        $($html).insertAfter('#' + $v.graphid + ' .graph')
        $('#' + $v.graphid + ' .bar').css('width', $barW + 'px')
      }

      /**
       * Animates the Bars to the correct heights.
       **/
      function animateBars($i) {
        if ($i == $v.values.length) {
          return
        }
        $('#' + $v.graphid + '_bar_' + $i).animate(
          {
            marginTop: '-' + ($v.heights[$i] + 1) + 'px',
            height: $v.heights[$i] + 'px',
          },
          $v.speed,
          'swing',
          function () {
            animateBars($i + 1)
          },
        )
      }
    </script>
  </head>
  <body>
    <script type="text/javascript">
      $(document).ready(function () {
        $graph_id = 'testgraph' // id of graph container
        $lines = 10 // number of lines
        $bar_margins = 30 // margins between the bars
        $bar_speed = 500 // speed for bar animation in milliseconds
        $animate = true // set to false if multiple charts on one page
        graphit($graph_id, $lines, $bar_margins, $bar_speed, $animate)
      })
    </script>
    <table id="testgraph" class="graphtable">
      <tr>
        <td>
          <div class="gCont">
            <div class="graph"></div>
          </div>
        </td>
        <td class="values">
          <label
            >First Number:<span style="background-color: #06F;">34</span></label
          >
          <label
            >Second Number:<span style="background-color: #C60;"
              >20</span
            ></label
          >
          <label
            >Third Number:<span style="background-color: #936;">15</span></label
          >
          <label
            >Fourth Number:<span style="background-color: #96C;"
              >30</span
            ></label
          >
          <label
            >Fifth Number:<span style="background-color: #396;">18</span></label
          >
        </td>
      </tr>
    </table>
  </body>
</html>

Legacy Comments Archive

This post originally appeared on my old site and has been recovered from the archives. Below are the original comments from the community.

k
kieren
February 8, 2011

i am 13 and i tried to get that animation at the top of the bar chasrt can u help me do it plz

e
eligeske Author
February 8, 2011

Hi kieuren, The email you left is getting kicked back.

z
zo_h
February 18, 2011

Very nice Bar Chart. Some time ago, I did something similar on the my wife homepage. Look at this: http://www.gohha.com/o_mnie.html (page footer). Very basic HTML, some CSS, transparent PNG and jquery support.

p
pkw-vermietung
February 18, 2011

Sir I am very much glad. I am searching this script for a long time. Again thaknx

S
Sam
June 22, 2011

Hi, Can you please tell me how to change the value “0″ in the vertical line of the graph, to the bottom adjacent to the bottom most line of the graph? The scale is not exactly correct.

e
eligeske Author
June 22, 2011

Hey Sam, Glad to help, can you send me a link with what you’re working on so I can get a better idea of what issue is?

S
Sam
June 22, 2011

Hi Eli, Thanks for replying. In the same link, there is Animated jQuery Bar Chart present. I wanna know what changes i’ve to make in this code for the 0 value in the vertical line of the chart to come to the bottommost horizontal line of the chart. As you can see that “0″ doesn’t have any horizontal line, horizontal lines only start from “4″. I hope i’ve made my doubt clear.

e
eligeske Author
June 23, 2011

Hi Sam, I tried the email you provided to request the file. Just in case that was the incorrect email address, here is my findings: you can try this changing the css for .graph to:

.graph {
  margin-left: 35px;
  border-bottom: 1px solid #ccc;
  border-top: 1px solid #ccc;
}
A
Ajmal
October 29, 2011

negative values are not displayed – pls add how it can be displayed

e
eligeske Author
November 14, 2011

Hi Ajmal, Sorry didn’t really plan on using it for negative numbers. But I’m sure with a little tinkering around someone may be able to get it to use them.

B
Benoit
July 25, 2012

Im trying to make the animation start with a button but it doesnt work!

e
eligeske Author
July 25, 2012

Hi Benoit, I have updated the download zip with a new file called BarChart_New. The code is now restructured in that file to a re-usable class and if animation is set to true, you must run the animateBars() function to show the bars. This way you can add it to an event, such as “onClick”.