skip to content

CSS: An actual 3d bar chart

 Tweet4 Shares0 Tweets

This article presents an experiment in creating a three dimensional bar chart that actually uses the 3D effects of perspective and rotation rather than just the skew transformation. The result should be a chart than can be viewed from any direction.

The code and example below will work best in WebKit browsers, and reasonably well in Firefox (v13).

Setting up the grid

As in other examples, we first set up a #stage element in which we can define the perspective at which any 3D tranformations will be viewed - basically where the viewer is in relation to the flat screen. Then, because we're creating a graph, we need to set up the axes and a grid (#chart).

While we could have easily created a background image and tile it to form a grid pattern, we decided instead to make use of the CSS linear gradients syntax. In all the code below the -moz- styles simply duplicate the -webkit- styles.

<style type="text/css"> #stage { -webkit-perspective: 1200px; -webkit-perspective-origin: 0% 0%; -moz-perspective: 1200px; -moz-perspective-origin: 0% 0%; background: rgba(0,255,255,0.2); } #chart { position: relative; margin: 1em auto; width: 400px; height: 160px; border: 1px solid #000; background: -webkit-repeating-linear-gradient(left, rgba(0,0,0,0) 0, rgba(0,0,0,0) 38px, #ccc 40px), -webkit-repeating-linear-gradient(bottom, rgba(0,0,0,0), rgba(0,0,0,0) 38px, #ccc 40px); background: -moz-repeating-linear-gradient(left, rgba(0,0,0,0) 0, rgba(0,0,0,0) 38px, #ccc 40px), -moz-repeating-linear-gradient(bottom, rgba(0,0,0,0), rgba(0,0,0,0) 38px, #ccc 40px); -webkit-transform-origin: 50% 50%; -webkit-transform: rotateX(65deg); -webkit-transform-style: preserve-3d; -moz-transform-origin: 50% 50%; -moz-transform: rotateX(65deg); -moz-transform-style: preserve-3d; } </style>

The chart size is 400 x 160 pixels with a grid of 40 pixels. As you can see the background grid is made up of two repeating gradients running horizontally and vertically. The chart has been tilted away from the screen by 65 degrees.

Defining a bar in 3D

Each bar in/on the chart is made up of four sides and a cap. The styles here are for a generic bar CSS class which can then be used multiple times in different positions and colours. They are defined in the HTML as you will see shortly.

To picture the transformations that are being applied think of a vertical cross flat on the page. The four sides are then rotated away from us to form a column. Simple.

<style type="text/css"> .bar { position: absolute; bottom: 40px; margin: 0 4px; width: 32px; height: 40px; outline: 1px solid #000; text-align: center; line-height: 40px; -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; font-size: 20px; } .barfront, .barback, .barleft, .barright { position: absolute; outline: inherit; background: inherit; } .barfront { width: inherit; bottom: 0; -webkit-transform: rotateX(90deg); -webkit-transform-origin: 50% 100%; -moz-transform: rotateX(90deg); -moz-transform-origin: 50% 100%; } .barback { width: inherit; top: 0; -webkit-transform: rotateX(-90deg); -webkit-transform-origin: 50% 0; -moz-transform: rotateX(-90deg); -moz-transform-origin: 50% 0; } .barright { height: inherit; right: 0; -webkit-transform: rotateY(-90deg); -webkit-transform-origin: 100% 50%; -moz-transform: rotateY(-90deg); -moz-transform-origin: 100% 50%; } .barleft { height: inherit; left: 0; -webkit-transform: rotateY(90deg); -webkit-transform-origin: 0% 50%; -moz-transform: rotateY(90deg); -moz-transform-origin: 0% 50%; } </style>

In the CSS code we haven't defined the position of the bar in the chart or it's colour. That needs to be done separately for each element. Note however that we've used the inherit property where possible to make this simple.

Bar chart HTML markup

Here you can see the code in practice as used for the demonstration below. There are three bars placed on the chart. Each bar is a div, with four child divs making up the four sides. You can have any number of bars and place them anywhere on the chart.

<div id="stage"> <div id="chart"> <div class="bar" style="left: 80px; background: rgba(255,0,0,0.8); -webkit-transform: translateZ(80px); -moz-transform: translateZ(80px);"> <div class="barfront" style="height: 80px;"></div> <div class="barback" style="height: 80px;"></div> <div class="barright" style="width: 80px;"></div> <div class="barleft" style="width: 80px;"></div> 20 </div> <div class="bar" style="left: 120px; background: rgba(0,127,255,0.8); -webkit-transform: translateZ(120px); -moz-transform: translateZ(120px);"> <div class="barfront" style="height: 120px;"></div> <div class="barback" style="height: 120px;"></div> <div class="barright" style="width: 120px;"></div> <div class="barleft" style="width: 120px;"></div> 30 </div> <div class="bar" style="left: 160px; background: rgba(255,255,0,0.8); -webkit-transform: translateZ(40px); -moz-transform: translateZ(40px);"> <div class="barfront" style="height: 40px;"></div> <div class="barback" style="height: 40px;"></div> <div class="barright" style="width: 40px;"></div> <div class="barleft" style="width: 40px;"></div> 10 </div> </div> </div>

In the code above you can see highlighted the code that sets the x-position of the bar in the chart as well as the height of each bar (which needs to be defined for each element making up the bar). In there as well are the colours (red, blue, yellow) to which we've applied a slight transparency.

The final result

If you're using a WebKit browser (Safari, Chrome, iPhone, iPad) then you should see both a 3D bar chart as well as some sliders which can be used for modifying some values. In Firefox the bar chart has some artefacts and the sliders are rendered as plain input boxes, but still work. Other browsers don't yet support the 3D transformations.

(0 .. 100%) (0 .. 90 degrees) (0 .. 60)

The sliders (or input fields) will affect, in order: the left/right positioning of the perspective origin; the rotation of the chart into the page; and the height of the centre (blue) column. This is the only part that requires JavaScript to implement. Enjoy.

A screen capture of the initial position for anyone using a non-supported browser:

1 | 2 | 3

If you have any questions or comments or make use of this in one of your own projects please let us know using the Feedback form below.


Send a message to The Art of Web:

used only for us to reply, and to display your gravatar.


<- copy the digits from the image into this box

press <Esc> or click outside this box to close

User Comments

Post your comment or question

11 October, 2016

Fix for artifacts in FireFox (comes from outline - change it to border):

.bar {
position: absolute;
bottom: 40px;
margin: 0 4px;
width: 32px;
height: 40px;
/* outline: 1px solid #000; */
border-style: solid;
border-width: 1px;
text-align: center;
line-height: 40px;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
font-size: 18px;
.barfront, .barback, .barleft, .barright {
position: absolute;
/* outline: inherit; */
border-style: inherit;
border-width: inherit;
background: inherit;

17 August, 2016

This is very good example of 3D chart. Can you please provide the javascript code so that it will be easy to understand the chart with its input fields

The Javascript code is in the HTML for the sliders:

x-axis rotation: <input type="range" size="3" max="90" value="65" onchange="
this.value = parseInt(this.value);
document.getElementById('chart').style['WebkitTransform'] = 'rotateX(' + this.value + 'deg)';
document.getElementById('chart').style['MozTransform'] = 'rotateX(' + this.value + 'deg)';
"> (0 .. 90 degrees)