JLION.COM
How to create a Gantt Chart in HTML
07/22/2007 Charting

How to create a Gantt chart in HTML

GANTT charts are not just for projects. They are an effective way to show the relationships between any types of event that have a duration; Gantt charts allow viewers to see at a glance which events happen during the same time period and which events have a much shorter or longer duration than others. GANTT charts can also illustrate dependency relationships between events, such as when there is a task that must be completed before another task begins.

If you’re not already a believer in Gantt charts, then I invite you to read the Wikipedia entry on Gantt charts, or this forum on Edward Tufte’s web site.

If you are a Gantt chart apostle then you may think that you need lots of graphics code or a charting library to add Gantt charts to your application. Nothing could be further from the truth. As I’m going to show you here, attractive gantt charts can be added to your application quickly and with a minimum of fuss.

Marshal your Data

The first step, as always, is to gather your data. This part of creating a Gantt chart is often the most time consuming, especially when you must marshal together time periods from different sources (for example, employee days off, in days, and customer appointments as a starting date/time with a duration).

Start off by determining what time frame you’re going to be illustrating with the Gantt chart. Will it be one day? One week? Also, what time units are you going to use? One day in one hour units is a different chart than one day in one minute units.

You will need to calculate the total number of time units in the chart time frame. Here by time units I mean minutes, hours, days, whatever measure of time you intend to use to compare event durations. So if the Gantt chart will show appointments for a particular day between 9:00 AM and 5:00 PM and you’ll be using hours as your time unit then the number of units will be 8. However, if you’ll be using one minute segments as your time unit, then the number would be 480)

Do the Math

Now you need the data for the individual events. In this article, I’m going to describe how to display one bar in the Gantt chart for each event. It’s not difficult to display multiple bars so you could, for example, show downtime for items of manufacturing equipment that could be down multiple times in a single day. The methods described here can be easily and logically extended to show multiple bars.

For each event that you intend to display, you’ll need this data:

  • Whatever text that will be displayed in the description columns for the bar.
  • The delay between the beginning of the event and the beginning of your chart’s time frame, measured in the same time units that you selected above. For example, if your time frame is 9:00 AM to 5:00 PM, your time unit is one minute and a particular event starts at 11:00 AM then the delay is 2 hours or 120 one minute time units.)
  • The duration of the event in time units. So if an event lasts for an hour and you are using one minute time units then the duration is 60 minutes or 60 one minute time units.

As an example, I’m going to show here how to create a gantt chart showing customer appointments for a single one day 9:00 AM to 5:00 PM period. For this example, I’m going to use the sample data shown below:

descriptionstarting_timeending_time
james bond10:3011:00
sally may11:3013:30
jerry jones11:3012:30
Mike Moxie12:3013:00
Carl Cluff13:0014:00
Mad Max14:0014:30

To display this data as a gantt chart, we need two additional fields for each row. Since we’re using minutes as our time unit we can easily calculate the values in both columns using the SQL datediff or VB datediff function :

description starting_time ending_time Delay_from_start Duration
james bond10:3011:009030
sally may11:30 13:30150120
jerry jones11:3012:3015060
Mike Moxie12:3013:0018030
Carl Cluff13:0014:0018060
Mad Max14:0014:3030030

Show the Picture

From here the going is all downhill. Our next step is to decide how big our gantt chart will be and create a table with a column of that size. For this example, we’ll make our gantt chart 200 pixels wide.

<table>
<tr>
	<td>description</td>
	<td>starting time</td>
	<td>duration</td>
	<td style=”width: 200px;”>Gant Chart</td>
</tr>

Now, we transform both the delay from start and duration columns into pixels. We do this by first converting both values to a percentage of the total duration then multiplying that percentage by the width of the chart in pixels.

Since this example gantt chart will show an 8 hour time period and will show it in minutes, the total duration of the chart time frame is 8 * 60 or 480.

To convert the time delay and duration periods to percentages, we simply divide both values by 480. Here’s the sample values converted to percentages.

description Starting time Delay from start Delay % Duration Duration %
james bond10:30900.19300.06
sally may11:301500.311200.25
jerry jones11:301500.31600.13
Mike Moxie12:301800.38300.06
Carl Cluff13:001800.38600.13
Mad Max14:003000.63300.06

Now we convert the percentages to pixels by multiplying them by the width of our gantt chart column (200 pixels).

description Starting time Delay from start Delay % Delay pixels Duration Duration % Duration Pixels
james bond10:30900.1937.5300.0612.5
sally may11:301500.3162.51200.2550
jerry jones11:301500.3162.5600.1325
Mike Moxie12:301800.3875300.0612.5
Carl Cluff13:001800.3875600.1325
Mad Max14:003000.63125300.0612.5

The last ingredient we need are the actual bars and indicators themselves. There are a lot of creative options available to you here. You could, for example, use different colors or patterns to indicate different kinds of events such as red for a confirmed appointment, blue for a tentative one. You could also choose to combine several images into a composite so that each bar has that familiar dumbbell look.

Each bar starts out as a one pixel wide image. The image may also be one pixel high, or it might be higher if you wish to show a pattern. We then use CSS styles to stretch the images to the lengths we calculated each bar should be.

To keep our bars properly aligned, we also use a one pixel by one pixel transparent image. This image is stretched for form the delay duration offset.

Here are a few images, and what they look like as bars:

Original Stretched to 100 pixels wide Description
blue dot blue dot One pixel high blue dot in the middle of a 15 pixel high white line
red dot red dot One pixel high red dot stretched both vertically and horizontally
blue line blue line Fifteen pixel high blue line.

Our final Gantt chart looks like this:

GANTT Chart

Here’s the HTML for the chart, the creation of which can easily be automated with a simple script once you have the data and the calculations have been performed. Note that the image tags for all images to appear on a line (including the spacer image) must be on the same line for the chart to work properly.

<html>
<head>
<style type="text/css">
	td {
		font-family: arial;
		font-size: 10px;
	}
	
</style>
</head>
<body>
<table style="width: 400px;">
<tr>
	<td colspan="7">
		GANT chart
	</td>
</tr>
<tr>
	<td style="width: 150px; vertical-align: bottom;">description</td>
	<td style="width: 100px; vertical-align: bottom;">begintime</td>
	<td style="width: 50px; vertical-align: bottom;">iduration</td>
	<td style="width: 200px; vertical-align: bottom;">
		<table style="width: 200px;">
		<tr>
			<td colspan="2" style="text-align: center; width:120px;">GANT Indicator</td>
		</tr>
		<tr>
			<td style="text-align: left; width: 100px;">9AM</td>
			<td style="text-align: right;width: 100px;">5PM</td>
		</tr>
		</table>
	</td>
</tr>

<tr>
	<td>james bond</td>
	<td>10:30</td>
	<td>90</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="37.5px;"><img src="images/busy.gif" height="15px;" width="12.5px;">
	</td>
</tr>

<tr>
	<td>sally may</td>
	<td>11:30</td>
	<td>120</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="62.5px;"><img src="images/bluebar.gif" height="15px;" width="2px;"><img src="images/blue-line.gif" height="15px;" width="46px;"><img src="images/bluebar.gif" height="15px;" width="2px;">
	</td>
</tr>

<tr>
	<td>jerry jones</td>
	<td>11:30</td>
	<td>60</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="62.5px;"><img src="images/busy.gif" height="15px;" width="25px;">
	</td>
</tr>

<tr>
	<td>Mike Moxie</td>
	<td>12:30</td>
	<td>30</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="75px;"><img src="images/busy.gif" height="15px;" width="12.5px;">
	</td>
</tr>

<tr>
	<td>Carl Cluff</td>
	<td>13:00</td>
	<td>60</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="75px;"><img src="images/busy.gif" height="15px;" width="25px;">
	</td>
</tr>

<tr>
	<td>Mad Max</td>
	<td>14:00</td>
	<td>30</td>
	
	<td style="border: solid 1px grey;">
	<img src="images/shim.gif" height="15px;" width="125px;"><img src="images/busy.gif" height="15px;" width="12.5px;">
	</td>
</tr>
</table>
</body>
</html>