People in boardrooms across the world love a good graph. They go nuts for PowerPoint, bullet points and phrases like “run it up the flagpole,” “blue-sky thinking” and “low-hanging fruit,” and everything is always “moving forward.” Backwards is not an option for people who facilitate paradigm shifts in the zeitgeist. Graphs of financial projections, quarterly sales figures and market saturation are a middle-manager’s dream.
How can we as Web designers get in on all of this hot graph action? There are actually quite a few ways to display graphs on the Web. We could simply create an image and nail it to a Web page. But that’s not very accessible or interesting. We could use Flash, which is quite good for displaying graphs — but again, not very accessible. Besides, designers, developers and deities are falling out of love with Flash. Technologies such as HTML5 can do many of the same things without the need for a plug-in. The new HTML5
There are pros and cons to the wide range of resources available to us, but this tutorial will not explore them all. Instead, we’ll create our graph using a progressively enhanced sprinkling of CSS3 and jQuery. Because we can.
Quick! You’ve just been given some alarming figures. The population of tanned zombies is projected to spiral out of control in the next few years. The carbon tigers and blue monkeys are under immediate threat. Then the tanned zombies will probably come for us. But you’re just a designer. What could you possibly do to help?
I know! You could make a Web page that illustrates our imminent demise with nice, calming, smoothly animated graphics!
To begin, let’s put this data into a table, with columns for each year, and rows for the different species.
View the example below to see how it looks naked, with no CSS or JavaScript applied. The accessibility of this table will enable people using screen readers to understand the data and the underlying message, which is “Run for your life! The zombies are coming!”
The easy part is now out of the way. Now, let’s tap into the power of CSS and JavasScript (via jQuery) to really illustrate what the numbers are telling us. Technically, our aim is to create a graph that works in all modern browsers, from IE 8 on.
Did I say all modern browsers? IE 8 is lucky: it gets to hang out with the cool kids. Browsers that support CSS3 will get a few extra sprinkles.
The first thing to do is style our table with some basic CSS. This is a nice safety net for people who haven’t enabled JavaScript in their browser.
Let’s get started by creating our main
Here’s our basic structure:
We pass two parameters to this function:
Nothing too exciting here, but these will be very useful later.
We have several functions here, and they are explained in the code’s comments. Most of them are quite similar, so we don’t need to go through each one. Instead, let’s pick apart one of them,
Here’s how it breaks down:
Here’s the code:
Excluding the headings, our table has five columns with three rows. For our graph, this means that for each column we create, three bars will appear in that column. The following image shows how our graph will be constructed:
Breaking it down:
Now that we have our bars, let’s work on labelling our graph. Because the code to display the labels is quite similar, talking you through all of it won’t be necessary. Here’s how we display the y-axis:
This breaks down as follows:
Before we can display our graph, we need to make sure that everything we’ve done is added to our container element.
We’re going to animate our graph sequentially, one by one, uno por uno.
One possible solution is to use a callback function to animate the next bar when the last animation is complete. However, the graph would take too long to animate. Instead, our graph will use a timer function to display each bar after a certain amount of time, regardless of how long each bar takes to grow. Rad!
Here’s the
What’s that you say? “Why aren’t you using the
The
You could, and it would work just fine… the first time. But if you tried to reset the animation via the “Reset graph” button, then the timing events wouldn’t clear properly and the bars would animate out of sequence.
I would like to be proven wrong, and if there is a better way to do this, feel free to sound off in the comments section.
Moving on, here’s
Let’s break
Not so fast, sunshine! Before we go any further, we need to put some clothes on.
Done. Let’s create a nice container area to put our graph in. Because a few unordered lists are being used to make our graph, we’ll also reset the styles for those. Giving the
Now for the legend. We position the legend right down to the bottom of its container (
The x-axis is very similar to the legend. We line up the elements horizontally and anchor them to the bottom of its container (
The y-axis is a little more involved and requires a couple of tricks. We give it a
Using the power of negative margins, we can offset the numerical labels inside the
Now for the meat in our endangered species sandwich: the bars themselves. Let’s start with the container element for the bars and the columns:
Nothing too complicated here. We’re simply setting some dimensions for the container, and setting a
Now for each individual
The main styles to note here are:
Because we’ve placed the values from each table cell in each bar, we can add a neat little pop-up that appears when you hover over a bar:
First, the pop-up is hidden from view via
The
Our final step in bringing everything together is to color code each bar:
In this example, I’ve simply added a
And, believe it or not, that is it!
That about wraps it up. I hope we’ve done enough to alert the public to the dangers of zombie over-population. More than that, however, I hope you’ve gained something useful from this tutorial and that you’ll continue to push the boundaries of what can be done in the browser — especially with proper Web standards and without the use of third-party plug-ins. If you’ve got ideas on how to extend or improve anything you’ve seen here, don’t hesitate to leave a comment below.
Because support for CSS3 properties is currently limited, so is their use. Although some of the features mentioned here are making their way into other Web browsers, Webkit-based ones such as Apple Safari and Google Chrome are leading the way.
We can actually create our graph using no images at all, and even animate the bars using CSS instead of jQuery.
Let’s start by removing the background images from our bars, replacing them with the
We can do the same with our little number pop-ups:
For more information on Webkit gradients, check out the Surfin’ Safari blog.
Continuing with the pop-ups, let’s introduce
Again, refer to Surfin’ Safari for more information on
Here’s an example:
When you hover over the bar, the margin and opacity of the pop-up will change. This triggers a transition event according to the properties we have set. Very cool.
Thanks to
Here are the main things we’ve changed:
As in our previous Webkit example, there are no images, and all animation is handled via CSS. Kiss my face!
I can’t tell you what to do with all this information. But I do caution you about the potential misuse of your new powers. In the words of our friend Captain Planet, “The power is yours!”
Use it wisely.
How can we as Web designers get in on all of this hot graph action? There are actually quite a few ways to display graphs on the Web. We could simply create an image and nail it to a Web page. But that’s not very accessible or interesting. We could use Flash, which is quite good for displaying graphs — but again, not very accessible. Besides, designers, developers and deities are falling out of love with Flash. Technologies such as HTML5 can do many of the same things without the need for a plug-in. The new HTML5
element could even be adapted to the task. Plenty of charting tools are online that we might use. But what if we wanted something a little more tailored?There are pros and cons to the wide range of resources available to us, but this tutorial will not explore them all. Instead, we’ll create our graph using a progressively enhanced sprinkling of CSS3 and jQuery. Because we can.
What Are We Making?
We’re making this. And more! Here are some possibilities on how you can extend the techniques explored in this tutorial:- A progress bar that indicates how long until the end of all humanity in the event of a zombie plague;
- A graph indicating the decline in safe outdoor activities during a zombie plague;
- A frighteningly similar graph indicating the decline in manners during a zombie plague;
- The increase of people who were unaware of the zombie plague because they were sharing with all of their now-deceased friends on Facebook what they did on FarmVille.
What You’ll Need
- A text or HTML editor. Take your pick; many are out there.
- jQuery. Practice safe scripting and get the latest one. Keep the jQuery website open so that you can look up the documentation as you go.
- Possibly an image editor, such as Paint, to mock up what your graph might look like.
- A modern and decent Web browser to preview changes.
The Mark-Up
You can create the underlying HTML for a graph in a number of ways. In this tutorial, we’ll start with atable
, because it will make the most sense visually if JavaScript or CSS is not applied. That’s a big checkmark in the column for accessibility.Quick! You’ve just been given some alarming figures. The population of tanned zombies is projected to spiral out of control in the next few years. The carbon tigers and blue monkeys are under immediate threat. Then the tanned zombies will probably come for us. But you’re just a designer. What could you possibly do to help?
I know! You could make a Web page that illustrates our imminent demise with nice, calming, smoothly animated graphics!
To begin, let’s put this data into a table, with columns for each year, and rows for the different species.
01 |
|
02 | < html lang = "en" > |
03 | < head > |
04 | < meta charset = "utf-8" > |
05 | < meta name = "viewport" content = "width=1024" > |
06 | < title >Example 01: No CSS |
07 |
|
08 |
09 | < body > |
10 | < div id = "wrapper" > |
11 | < div class = "chart" > |
12 | < h3 >Population of endangered species from 2012 to 2016 |
13 | < table id = "data-table" border = "1" cellpadding = "10" cellspacing = "0" |
14 | summary="The effects of the zombie outbreak on the populations |
15 | of endangered species from 2012 to 2016"> |
16 | < caption >Population in thousands |
17 | < thead > |
18 | < tr > |
19 | < td > |
20 | < th scope = "col" >2012 |
21 | < th scope = "col" >2013 |
22 | < th scope = "col" >2014 |
23 | < th scope = "col" >2015 |
24 | < th scope = "col" >2016 |
25 |
|
26 |
|
27 | < tbody > |
28 | < tr > |
29 | < th scope = "row" >Carbon Tiger |
30 | < td >4080 |
31 | < td >6080 |
32 | < td >6240 |
33 | < td >3520 |
34 | < td >2240 |
35 |
|
36 | < tr > |
37 | < th scope = "row" >Blue Monkey |
38 | < td >5680 |
39 | < td >6880 |
40 | < td >6240 |
41 | < td >5120 |
42 | < td >2640 |
43 |
|
44 | < tr > |
45 | < th scope = "row" >Tanned Zombie |
46 | < td >1040 |
47 | < td >1760 |
48 | < td >2880 |
49 | < td >4720 |
50 | < td >7520 |
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
The easy part is now out of the way. Now, let’s tap into the power of CSS and JavasScript (via jQuery) to really illustrate what the numbers are telling us. Technically, our aim is to create a graph that works in all modern browsers, from IE 8 on.
Did I say all modern browsers? IE 8 is lucky: it gets to hang out with the cool kids. Browsers that support CSS3 will get a few extra sprinkles.
“By Your Powers Combined…”
If you wish to summon Captain Planet, you may have to look elsewhere. If you want to learn how to combine CSS and jQuery to create a graph that illustrates our impending doom at the hands of a growing army of zombies who prefer bronzer over brains, then read on.The first thing to do is style our table with some basic CSS. This is a nice safety net for people who haven’t enabled JavaScript in their browser.
Getting Started In jQuery
We’ll use jQuery to create our graph on the fly, separate from the original data table. To do this, we need to get the data out of the table and store it in a more usable format. Then, we can add to our document new elements that use this data in order to construct our graph.Let’s get started by creating our main
createGraph()
function. I’ve abbreviated some of the inner workings of this function so that you get a clearer picture of the structure. Don’t forget: you can always refer to the source code that comes with this tutorial.Here’s our basic structure:
01 | // Wait for the DOM to load everything, just to be safe |
02 | $(document).ready( function () { |
03 |
04 | // Create our graph from the data table and specify a container to put the graph in |
05 | createGraph( '#data-table' , '.chart' ); |
06 |
07 | // Here be graphs |
08 | function createGraph(data, container) { |
09 | // Declare some common variables and container elements |
10 | … |
11 |
12 | // Create the table data object |
13 | var tableData = { |
14 | … |
15 | } |
16 |
17 | // Useful variables to access table data |
18 | … |
19 |
20 | // Construct the graph |
21 | … |
22 |
23 | // Set the individual heights of bars |
24 | function displayGraph(bars) { |
25 | … |
26 | } |
27 |
28 | // Reset the graph's settings and prepare for display |
29 | function resetGraph() { |
30 | … |
31 | displayGraph(bars); |
32 | } |
33 |
34 | // Helper functions |
35 | … |
36 |
37 | // Finally, display the graph via reset function |
38 | resetGraph(); |
39 | } |
40 | }); |
- The
data
, in the form of atable
element; - A
container
element, where we’d like to place our graph in the document.
01 | // Declare some common variables and container elements |
02 | var bars = []; |
03 | var figureContainer = $( ' ' ); |
04 | var graphContainer = $( ' ' ); |
05 | var barContainer = $( ' ' ); |
06 | var data = $(data); |
07 | var container = $(container); |
08 | var chartData; |
09 | var chartYMax; |
10 | var columnGroups; |
11 |
12 | // Timer variables |
13 | var barTimer; |
14 | var graphTimer; |
Getting The Data
Besides simply displaying the data, a good bar chart should have a nice big title, clearly labelled axes and a color-coded legend. We’ll need to strip the data out of the table and format it in a way that is more meaningful in a graph. To do that, we’ll create a JavaScript object that stores our data in handy little functions. Let’s give birth to ourtableData{}
object:01 | // Create table data object |
02 | var tableData = { |
03 | // Get numerical data from table cells |
04 | chartData: function () { |
05 | … |
06 | }, |
07 | // Get heading data from table caption |
08 | chartHeading: function () { |
09 | … |
10 | }, |
11 | // Get legend data from table body |
12 | chartLegend: function () { |
13 | … |
14 | }, |
15 | // Get highest value for y-axis scale |
16 | chartYMax: function () { |
17 | … |
18 | }, |
19 | // Get y-axis data from table cells |
20 | yLegend: function () { |
21 | … |
22 | }, |
23 | // Get x-axis data from table header |
24 | xLegend: function () { |
25 | … |
26 | }, |
27 | // Sort data into groups based on number of columns |
28 | columnGroups: function () { |
29 | … |
30 | } |
31 | } |
columnGroups
:01 | // Sort data into groups based on number of columns |
02 | columnGroups: function () { |
03 | var columnGroups = []; |
04 | // Get number of columns from first row of table body |
05 | var columns = data.find( 'tbody tr:eq(0) td' ).length; |
06 | for ( var i = 0; i < columns; i++) { |
07 | columnGroups[i] = []; |
08 | data.find( 'tbody tr' ).each( function () { |
09 | columnGroups[i].push($( this ).find( 'td' ).eq(i).text()); |
10 | }); |
11 | } |
12 | return columnGroups; |
13 | } |
- Create the
columnGroups[]
array to store the data; - Get the number of columns by counting the table cells (
td
) in the first row; - For each column, find the number of rows in the table body (
tbody
), and create another array to store the table cell data; - Then loop through each row and grab the data from each table cell (via the jQuery
text()
function), and then add it to the table cell data array.
Using The Data
Using the jQuery$.each
function, we can now loop through our data at any point and create the elements that make up our graph. One of the trickier bits involves inserting the bars that represent each species inside the yearly columns.Here’s the code:
01 | // Loop through column groups, adding bars as we go |
02 | $.each(columnGroups, function (i) { |
03 | // Create bar group container |
04 | var barGroup = $( ' ' ); |
05 | // Add bars inside each column |
06 | for ( var j = 0, k = columnGroups[i].length; j < k; j++) { |
07 | // Create bar object to store properties (label, height, code, etc.) and add it to array |
08 | // Set the height later in displayGraph() to allow for left-to-right sequential display |
09 | var barObj = {}; |
10 | barObj.label = this [j]; |
11 | barObj.height = Math.floor(barObj.label / chartYMax * 100) + '%' ; |
12 | barObj.bar = $( ' ' ) |
13 | .appendTo(barGroup); |
14 | bars.push(barObj); |
15 | } |
16 | // Add bar groups to graph |
17 | barGroup.appendTo(barContainer); |
18 | }); |
Breaking it down:
- For each column, create a container
div
; - Loop inside each column to get the row and cell data;
- Create a bar object (
barObj{}
) to store the properties for each bar, such as its label, height and mark-up; - Add the mark-up property to the column, applying a CSS class of
'.fig' + j
to color code each bar in the column, wrapping the label in aspan
; - Add the object to our
bars[]
array so that we can access the data later; - Piece it all together by adding the columns to a container element.
Now that we have our bars, let’s work on labelling our graph. Because the code to display the labels is quite similar, talking you through all of it won’t be necessary. Here’s how we display the y-axis:
1 | // Add y-axis to graph |
2 | var yLegend = tableData.yLegend(); |
3 | var yAxisList = $( ' ' ); |
4 | $.each(yLegend, function (i) { |
5 | var listItem = $( ' ' + this + ' ' ) |
6 | .appendTo(yAxisList); |
7 | }); |
8 | yAxisList.appendTo(graphContainer); |
- Get the relevant table data for our labels,
- Create an unordered list (
ul
) to contain our list items; - Loop through the label data, and create a list item (
li
) for each label, wrapping each label in aspan
; - Attach the list item to our list;
- Finally, attach the list to a container element.
Before we can display our graph, we need to make sure that everything we’ve done is added to our container element.
1 | // Add bars to graph |
2 | barContainer.appendTo(graphContainer); |
3 |
4 | // Add graph to graph container |
5 | graphContainer.appendTo(figureContainer); |
6 |
7 | // Add graph container to main container |
8 | figureContainer.appendTo(container); |
Displaying The Data
All that’s left to do in jQuery is set the height of each bar. This is where our earlier work, storing the height property in a bar object, will come in handy.We’re going to animate our graph sequentially, one by one, uno por uno.
One possible solution is to use a callback function to animate the next bar when the last animation is complete. However, the graph would take too long to animate. Instead, our graph will use a timer function to display each bar after a certain amount of time, regardless of how long each bar takes to grow. Rad!
Here’s the
displayGraph()
function:01 | // Set the individual height of bars |
02 | function displayGraph(bars, i) { |
03 | // Changed the way we loop because of issues with $.each not resetting properly |
04 | if (i < bars.length) { |
05 | // Animate the height using the jQuery animate() function |
06 | $(bars[i].bar).animate({ |
07 | height: bars[i].height |
08 | }, 800); |
09 | // Wait the specified time, then run the displayGraph() function again for the next bar |
10 | barTimer = setTimeout( function () { |
11 | i++; |
12 | displayGraph(bars, i); |
13 | }, 100); |
14 | } |
15 | } |
$.each
function like you have everywhere else?” Good question. First, let’s discuss what the displayGraph()
function does, then why it is the way it is.The
displayGraph()
function accepts two parameters:- The
bars
to loop through, - An index (
i
) from which to start iterating (starting at0
).
- If the value of
i
is less than the number of bars, then keep going; - Get the current bar from the array using the value of
i
; - Animate the height property (calculated as a percentage and stored in
bars[i].height
); - Wait 100 milliseconds;
- Increment
i
by 1 and repeat the process for the next bar.
$.each
function with a delay()
before the animation?”You could, and it would work just fine… the first time. But if you tried to reset the animation via the “Reset graph” button, then the timing events wouldn’t clear properly and the bars would animate out of sequence.
I would like to be proven wrong, and if there is a better way to do this, feel free to sound off in the comments section.
Moving on, here’s
resetGraph()
:01 | // Reset graph settings and prepare for display |
02 | function resetGraph() { |
03 | // Stop all animations and set the bar's height to 0 |
04 | $.each(bars, function (i) { |
05 | $(bars[i].bar).stop().css( 'height' , 0); |
06 | }); |
07 |
08 | // Clear timers |
09 | clearTimeout(barTimer); |
10 | clearTimeout(graphTimer); |
11 |
12 | // Restart timer |
13 | graphTimer = setTimeout( function () { |
14 | displayGraph(bars, 0); |
15 | }, 200); |
16 | } |
resetGraph()
down:- Stop all animations, and set the height of each bar back to 0;
- Clear out the timers so that there are no stray animations;
- Wait 200 milliseconds;
- Call
displayGraph()
to animate the first bar (at index0
).
resetGraph()
at the bottom of createGraph()
, and watch the magic happen as we bask in the glory of our hard work.Not so fast, sunshine! Before we go any further, we need to put some clothes on.
The CSS
The first thing we need to do is hide the original data table. We could do this in a number of ways, but because our CSS will load well before the JavaScript, let’s do this in the easiest way possible:1 | #data-table { |
2 | display : none ; |
3 | } |
#figure
and .graph
elements a position: relative
is important because it will anchor the place elements exactly where we want in those containers.01 | /* Containers */ |
02 |
03 | #wrapper { |
04 | height : 420px ; |
05 | left : 50% ; |
06 | margin : -210px 0 0 -270px ; |
07 | position : absolute ; |
08 | top : 50% ; |
09 | width : 540px ; |
10 | } |
11 |
12 | #figure { |
13 | height : 380px ; |
14 | position : relative ; |
15 | } |
16 |
17 | #figure ul { |
18 | list-style : none ; |
19 | margin : 0 ; |
20 | padding : 0 ; |
21 | } |
22 |
23 | .graph { |
24 | height : 283px ; |
25 | position : relative ; |
26 | } |
#figure
) and line up the items horizontally:01 | /* Legend */ |
02 |
03 | .legend { |
04 | background : #f0f0f0 ; |
05 | border-radius: 4px ; |
06 | bottom : 0 ; |
07 | position : absolute ; |
08 | text-align : left ; |
09 | width : 100% ; |
10 | } |
11 |
12 | .legend li { |
13 | display : block ; |
14 | float : left ; |
15 | height : 20px ; |
16 | margin : 0 ; |
17 | padding : 10px 30px ; |
18 | width : 120px ; |
19 | } |
20 |
21 | .legend span. icon { |
22 | background-position : 50% 0 ; |
23 | border-radius: 2px ; |
24 | display : block ; |
25 | float : left ; |
26 | height : 16px ; |
27 | margin : 2px 10px 0 0 ; |
28 | width : 16px ; |
29 | } |
.graph
):01 | /* x-axis */ |
02 |
03 | .x-axis { |
04 | bottom : 0 ; |
05 | color : #555 ; |
06 | position : absolute ; |
07 | text-align : center ; |
08 | width : 100% ; |
09 | } |
10 |
11 | .x-axis li { |
12 | float : left ; |
13 | margin : 0 15px ; |
14 | padding : 5px 0 ; |
15 | width : 76px ; |
16 | } |
position: absolute
to break it out of the normal flow of content, but anchored to its container. We stretch out each li
to the full width of the graph and add a border across the top. This will give us some nice horizontal lines in the background.Using the power of negative margins, we can offset the numerical labels inside the
span
so that they shift up and to the left. Lovely!01 | /* y-axis */ |
02 |
03 | .y-axis { |
04 | color : #555 ; |
05 | position : absolute ; |
06 | text-align : right ; |
07 | width : 100% ; |
08 | } |
09 |
10 | .y-axis li { |
11 | border-top : 1px solid #ccc ; |
12 | display : block ; |
13 | height : 62px ; |
14 | width : 100% ; |
15 | } |
16 |
17 | .y-axis li span { |
18 | display : block ; |
19 | margin : -10px 0 0 -60px ; |
20 | padding : 0 10px ; |
21 | width : 40px ; |
22 | } |
01 | /* Graph bars */ |
02 |
03 | .bars { |
04 | height : 253px ; |
05 | position : absolute ; |
06 | width : 100% ; |
07 | z-index : 10 ; |
08 | } |
09 |
10 | .bar-group { |
11 | float : left ; |
12 | height : 100% ; |
13 | margin : 0 15px ; |
14 | position : relative ; |
15 | width : 76px ; |
16 | } |
z-index
to make sure it appears in front of the y-axis markings.Now for each individual
.bar
:01 | .bar { |
02 | border-radius: 3px 3px 0 0 ; |
03 | bottom : 0 ; |
04 | cursor : pointer ; |
05 | height : 0 ; |
06 | position : absolute ; |
07 | text-align : center ; |
08 | width : 24px ; |
09 | } |
10 |
11 | .bar.fig 0 { |
12 | left : 0 ; |
13 | } |
14 |
15 | .bar.fig 1 { |
16 | left : 26px ; |
17 | } |
18 |
19 | .bar.fig 2 { |
20 | left : 52px ; |
21 | } |
position: absolute
andbottom: 0
, which means that the bars will be attached to the bottom of our graph and grow up;- the bar for each species (
.fig0
,.fig1
and.fig2
), which will be positioned within.bar-group
.
border-radius
property to round the edges of the top-left and top-right corners of each bar? OK, so border-radius
isn’t really necessary, but it adds a nice touch for browsers that support it. Thankfully, the latest versions of the most popular browsers do support it.Because we’ve placed the values from each table cell in each bar, we can add a neat little pop-up that appears when you hover over a bar:
01 | .bar span { |
02 | #fefefe url (../images/info-bg.gif) 0 100% repeat-x ; |
03 | border-radius: 3px ; |
04 | left : -8px ; |
05 | display : none ; |
06 | margin : 0 ; |
07 | position : relative ; |
08 | text-shadow : rgba( 255 , 255 , 255 , 0.8 ) 0 1px 0 ; |
09 | width : 40px ; |
10 | z-index : 20 ; |
11 |
12 | -webkit-box-shadow: rgba( 0 , 0 , 0 , 0.6 ) 0 1px 4px ; |
13 | box-shadow: rgba( 0 , 0 , 0 , 0.6 ) 0 1px 4px ; |
14 | } |
15 |
16 | .bar:hover span { |
17 | display : block ; |
18 | margin-top : -25px ; |
19 | } |
display: none
. Then, when a .bar
element is hovered over, we’ve set display: block
to bring it into view, and set a negative margin-top
to make it appear above each bar.The
text-shadow
, rgba
and box-shadow
properties are currently supported by most modern browsers as is. Of these modern browsers, only Safari requires a vendor prefix (-webkit-
) to make box-shadow
work. Note that these properties are simply enhancements to our graph and aren’t required to understand it. Our baseline of Internet Explorer 8 simply ignores them.Our final step in bringing everything together is to color code each bar:
01 | .fig 0 { |
02 | background : #747474 url (../images/bar -01 -bg.gif) 0 0 repeat-y ; |
03 | } |
04 |
05 | .fig 1 { |
06 | background : #65c2e8 url (../images/bar -02 -bg.gif) 0 0 repeat-y ; |
07 | } |
08 |
09 | .fig 2 { |
10 | background : #eea151 url (../images/bar -03 -bg.gif) 0 0 repeat-y ; |
11 | } |
background-color
and a background-image
that tiles vertically. This will update the styles for the bars and the little icons that represent them in the legend. Nice.And, believe it or not, that is it!
The Finished Product
That about wraps it up. I hope we’ve done enough to alert the public to the dangers of zombie over-population. More than that, however, I hope you’ve gained something useful from this tutorial and that you’ll continue to push the boundaries of what can be done in the browser — especially with proper Web standards and without the use of third-party plug-ins. If you’ve got ideas on how to extend or improve anything you’ve seen here, don’t hesitate to leave a comment below.
Bonus: Unleashing The Power Of CSS3
This bonus is not as detailed as our main example. It serves mainly as a showcase of some features being considered in the CSS3 specification.Because support for CSS3 properties is currently limited, so is their use. Although some of the features mentioned here are making their way into other Web browsers, Webkit-based ones such as Apple Safari and Google Chrome are leading the way.
We can actually create our graph using no images at all, and even animate the bars using CSS instead of jQuery.
Let’s start by removing the background images from our bars, replacing them with the
-webkit-gradient
property:01 | .fig 0 { |
02 | background : -webkit-gradient(linear, left top , right top , color-stop( 0.0 , #747474 ), color-stop( 0.49 , #676767 ), color-stop( 0.5 , #505050 ), color-stop( 1.0 , #414141 )); |
03 | } |
04 |
05 | .fig 1 { |
06 | background : -webkit-gradient(linear, left top , right top , color-stop( 0.0 , #65c2e8 ), color-stop( 0.49 , #55b3e1 ), color-stop( 0.5 , #3ba6dc ), color-stop( 1.0 , #2794d4 )); |
07 | } |
08 |
09 | .fig 2 { |
10 | background : -webkit-gradient(linear, left top , right top , color-stop( 0.0 , #eea151 ), color-stop( 0.49 , #ea8f44 ), color-stop( 0.5 , #e67e28 ), color-stop( 1.0 , #e06818 )); |
11 | } |
1 | .bar span { |
2 | background : -webkit-gradient(linear, left top , left bottom , color-stop( 0.0 , #fff ), color-stop( 1.0 , #e5e5e5 )); |
3 | … |
4 | } |
Continuing with the pop-ups, let’s introduce
-webkit-transition
. CSS transitions are remarkably easy to use and understand. When the browser detects a change in an element’s property (height, width, color, opacity, etc.), it will transition to the new property.Again, refer to Surfin’ Safari for more information on
-webkit-transition
and CSS3 animation.Here’s an example:
01 | .bar span { |
02 | background : -webkit-gradient(linear, left top , left bottom , color-stop( 0.0 , #fff ), color-stop( 1.0 , #e5e5e5 )); |
03 | display : block ; |
04 | opacity: 0 ; |
05 |
06 | -webkit-transition: all 0.2 s ease-out; |
07 | } |
08 |
09 | .bar:hover span { |
10 | opacity: 1 ; |
11 | } |
Thanks to
-webkit-transition
, we can simplify our JavaScript functions a bit:01 | // Set individual height of bars |
02 | function displayGraph(bars, i) { |
03 | // Changed the way we loop because of issues with $.each not resetting properly |
04 | if (i < bars.length) { |
05 | // Add transition properties and set height via CSS |
06 | $(bars[i].bar).css({ 'height' : bars[i].height, '-webkit-transition' : 'all 0.8s ease-out' }); |
07 | // Wait the specified time, then run the displayGraph() function again for the next bar |
08 | barTimer = setTimeout( function () { |
09 | i++; |
10 | displayGraph(bars, i); |
11 | }, 100); |
12 | } |
13 | } |
14 | // Reset graph settings and prepare for display |
15 | function resetGraph() { |
16 | // Set bar height to 0 and clear all transitions |
17 | $.each(bars, function (i) { |
18 | $(bars[i].bar).stop().css({ 'height' : 0, '-webkit-transition' : 'none' }); |
19 | }); |
20 |
21 | // Clear timers |
22 | clearTimeout(barTimer); |
23 | clearTimeout(graphTimer); |
24 |
25 | // Restart timer |
26 | graphTimer = setTimeout( function () { |
27 | displayGraph(bars, 0); |
28 | }, 200); |
29 | } |
- Set the height of the bars via the jQuery
css()
function, and allowed CSS transitions to take care of the animation; - When resetting the graph, turned transitions off so that the height of the bars is instantly set to 0.
Ultra-Mega Webkit Bonus: Now In 3-D!
For a sneak peek of what the future holds, check out a little experiment that I put together, with a 3-D effect and CSS transforms. Again, it requires the latest versions of Safari or Chrome:As in our previous Webkit example, there are no images, and all animation is handled via CSS. Kiss my face!
I can’t tell you what to do with all this information. But I do caution you about the potential misuse of your new powers. In the words of our friend Captain Planet, “The power is yours!”
Use it wisely.
No comments:
Post a Comment