site logo

Sandwich graph

When each bar in bar graph is splitted to a few layers sandwich graph can be created. While total height of columns indicates global trend, the height of single layer (usually in varied color) indicates portion or share of this layer. For example total trend sales and regions, or brands share.

Graph example in this article comes from production reports application. Graph does not display trend, but number of good and defective products recalculated to corresponding time and downtime. Green portion of column marks time when only good pieces were produced, yellow is for defective pieces and orange is downtime. Sum of these times should result in 24 hours. Target of graph is visualisation of production line efficiency and prompt verification of entered data.

Sandwich graph values comes from real monthly production graph, and is shorten to 14 days. Images for bar drawing are borrowed from application raw material stock.

24 h
16 h
8 h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
 good
 defect
 downtime

For drawing sandwich graph, several pictures are needed. Background graph picture includes scale lines and dark gray part for legend. Part of background can be also description of scale, if worsen quality at printing admitted.

It is possible to experiment with bar images. There is only one limitation, bar must be symetrical in one axis. For vertical bar graph balancing in horizontal axis is required.

It proved to me the minimal height of bar image 16 pixels. Images less then 8 pixels, when magnified more than 10 times in one axis, sometime disappears. But it was many years ago in old browser.


<style type="text/css">
/* graph bar: container, graph bar, holiday, workday */
.C {position: relative; width: 23px; left: 0; top:0; height:205px; float:left;}
.G {position: absolute; width: 20px; left: 0; z-index: 1;}
.DH, .DW {position: absolute; width: 20px; left: 0; top: 289px;
          z-index: 2; text-align: center;}
.DH {background: #fdd;}
.DW {background: #ddd;}

/* Y-axis description */
.Y {position: relative; left: 6px;}

/* legend below graph: text, image */
.Lt {position: relative; top: 0; left: 0; width:  92px; height: 16px;
     border: 0; float: left;}
.Li {width: 20px; height: 12px; border: 0;}
</style>

<body>

<div style="position: relative; width: 364px; height: 330px;">
<img style="position: absolute; width: 364px; height: 330px; top: 0; left: 0; 
  z-index: 0;" src="card.png" />

<div class="C" style="width: 36px;">
<div class="Y" style="top: 26px;">24 h</div>
<div class="Y" style="top: 96px;">16 h</div>
<div class="Y" style="top:166px;"> 8 h</div>
</div>
...
<div class="C">
<img class="G" style="top: 57px; height: 229px;" src="barGreen.png" />
<img class="G" style="top: 35px; height: 22px;" src="barYellow.png" />
<div class="DH">2</div>
</div>

<div class="C">
<img class="G" style="top: 106px; height: 180px;" src="barGreen.png" />
<img class="G" style="top:  98px; height:  8px;" src="barYellow.png" />
<img class="G" style="top:  31px; height: 67px;" src="barOrange.png" />
<div class="DW">3</div>
</div>
...

<div class="Lt" style='width: 36px;'>&nbsp;</div>
<div class="Lt"><img class="Li" src="barGreen.png" />good</div>
<div class="Lt"><img class="Li" src="barYellow.png" />defect</div>
<div class="Lt"><img class="Li" src="barOrange.png" />downtime</div>

</div>

</body>

In CSS section classes for graph drawing are declared. Class .C is container for one column drawing and for calendar below graph. This class has position relative, so that inside of container it would be possible to use position absolute. Class .G serves for drawing single bar in column. Classes .DW and .DH are for date rendering, they distinguish working days (.DW) and holidays (.DH) by its background colour. Further there are classes for scale description .Y and .Lt, .Li for legend, that are placed below graph.

HTML code. Graph area is defined in tag <div ...>, by inline style and acts as global container for complete graph. Graph background picture (card.png) follows. Picture has the same proportions as graph container. Now Y axis description is drawn. Into local container .C are placed 3 div elements with scale description, each element has inline position top, in order to place text next to horizontal lines of background picture.

In HTML code only two columns of graph are listed. Each column is located inside of local container <div class="C">. These local containers "float to the left" thanks to style float: left and queue themself until the whole width of outer graph container is filled. Inside of local container single bars (layers) are placed. Single bars are positioned as absolute in CSS section, parameters top and height are assigned by inline style.

If the hight of some single bar is zero, I would recommend to skip this part of HTML code. Some browsers do not love pictures with zero height. Last line inside of local container is date. Server script should select corresponding CSS class for date according to working day or holiday. Only day of date is displayed. Month and year are published somewhere in title.

In the end legend is rendered. Because of total width of global graph container is already utilized by graph columns, position relative for legend is used. Legend elements are drawn below dates than. If graph has flexible total number of columns this method may cause problems, in such a case position absolute for class .Lt should be used.

updated 2023-10-31