block by davo cd7f60da81f3dd9c5ede3633053b48e3

A Material Design Gauge in Pure CSS/HTML

Full Screen

As a change of pace from complex visualizations, here’s simple Material Design gauge control implemented in pure CSS/HTML. The implementation includes an optional JavaScript component to change the gauge value dynamically. If you’d like to use the gauge on your web pages (it’s open source), you can download it from GitHub, where you’ll also find documentation on how to use it. In this post we’ll walk through the implementation to understand how it works.

forked from sathomas‘s block: A Material Design Gauge in Pure CSS/HTML

index.html

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>Material Design Gauge</title>
        <meta name="description" 
              content="Simple Material Design gauge control implemented in pure CSS/HTML">
        <meta name="viewport" content="width=device-width, initial-scale=1">
		<style>

			body {
				color: #444;
				font-family: Varela, Helvetica, Arial, sans-serif;
				font-size: 24px;
				font-weight: normal;
				height: 32px;
				letter-spacing: normal;
				line-height: 32px;
			}
			
			p {
				text-align: center;
			}

			/*
			 * #### Gauge Component
			 *
			 * The standard markup for the component is:
			 *
			 *      <div class="gauge">
			 *          <div class="gauge--container">
			 *              <div class="gauge--marker"></div>
			 *              <div class="gauge--background"></div>
			 *              <div class="gauge--center"></div>
			 *              <div class="gauge--data"></div>
			 *              <div class="gauge--needle"></div>
			 *          </div>
			 *          <div class="gauge--labels">
			 *              <span class="gauge--label__low">No</span>
			 *              <span class="gauge--label__spacer"></span>
			 *              <span class="gauge--label__high">Yes</span>
			 *          </div>
			 *      </div>
			 */
 
			/*
			 * First define all of the relevant rules that aren't dependent
			 * on the size of the gauge. We want to collect the size-depenent
			 * rules in one place to make it easier to adjust the size.
			 */

			.gauge {
			    position: relative;
			}

			.gauge--container {
				margin: 0;
				padding: 0;
				position: absolute;
				left: 50%;
				overflow: hidden;
				text-align: center;
				-webkit-transform: translateX(-50%);
				   -moz-transform: translateX(-50%);
				    -ms-transform: translateX(-50%);
				     -o-transform: translateX(-50%);
				        transform: translateX(-50%);
			}

			.gauge--background {
				z-index: 0;
				position: absolute;
				background-color: #C0D3D3;
				top: 0;
				border-radius: 300px 300px 0 0;
			}

			.gauge--data {
				z-index: 1;
				position: absolute;
				background-color: #007979;
				margin-left: auto;
				margin-right: auto;
				border-radius: 300px 300px 0 0;
			    -webkit-transform-origin: center bottom;
			       -moz-transform-origin: center bottom;
			        -ms-transform-origin: center bottom;
			         -o-transform-origin: center bottom;
			            transform-origin: center bottom;
			}

			.gauge--center {
				z-index: 2;
				position: absolute;
				background-color: #fff;
				margin-right: auto;
				border-radius: 300px 300px 0 0;
			}

			.gauge--marker {
			    z-index: 3;
			    background-color: #fff;
			    position: absolute;
			    width: 1px;
			}

			.gauge--needle {
			    z-index: 4;
			    background-color: #F77C15;
			    height: 3px;
			    position: absolute;
			    -webkit-transform-origin: left center;
			       -moz-transform-origin: left center;
			        -ms-transform-origin: left center;
			         -o-transform-origin: left center;
			            transform-origin: left center;
			}

			.gauge--labels {
			    display: table;
			    margin: 0 auto;
			    position: relative;
			}

			.gauge--label__low {
			    display: table-cell;
			    text-align: center;
			}

			.gauge--label__spacer {
			    display: table-cell;
			}

			.gauge--label__high {
			    display: table-cell;
			    text-align: center;
			}

			/*
			 * Now define the rules that depend on the size of
			 * the gauge. We start with sizing for a small mobile
			 * device.
			 */

			.gauge { height: calc(120px + 3em); }
			.gauge--container { width: 240px; height: 120px; }
			.gauge--marker { height: 120px; left: 119.5px; }
			.gauge--background { width: 240px; height: 120px; }
			.gauge--center { width: 144px; height: 72px; top: 48px; margin-left: 48px; }
			.gauge--data { width: 240px; height: 120px; }
			.gauge--needle { left: 120px; top: 117px; width: 120px; }
			.gauge--labels { top: 120px; width: 240px; }
			.gauge--label__low { width: 48px; }
			.gauge--label__spacer { width: 144px; }
			.gauge--label__high { width: 48px; }

			/*
			 * Increase the gauge size slightly on larger viewports.
			 */

			 @media only screen and (min-width: 400px) {
			    .gauge { height: calc(150px + 3em); }
			    .gauge--container { width: 300px; height: 150px; }
			    .gauge--marker { height: 150px; left: 149.5px; }
			    .gauge--background { width: 300px; height: 150px; }
			    .gauge--center { width: 180px; height: 90px; top: 60px; margin-left: 60px; }
			    .gauge--data { width: 300px; height: 150px; }
			    .gauge--needle { left: 150px; top: 147px; width: 150px; }
			    .gauge--labels { top: 150px; width: 300px; }
			    .gauge--label__low { width: 60px; }
			    .gauge--label__spacer { width: 180px; }
			    .gauge--label__high { width: 60px; }
			}

			/*
			 * As an option, the `gauge__liveupdate` class can be added
			 * to the main gauge element. When this class is present,
			 * we add a transition that animates any changes to the gauge
			 * value. Currently, the app does not use this option because
			 * all the inputs that can change gauge values are present
			 * on tab panels that are different from the gauge itself.
			 * Therefore, users won't be able to see any gauge changes
			 * when they make input changes. The code is available, though,
			 * should this change.
			 */

			.gauge__liveupdate .gauge--data,
			.gauge__liveupdate .gauge--needle {
			    -webkit-transition: all 1s ease-in-out;
			       -moz-transition: all 1s ease-in-out;
			        -ms-transition: all 1s ease-in-out;
			         -o-transition: all 1s ease-in-out;
			            transition: all 1s ease-in-out;
			}            

			/*
			 * For a given gauge value, x, ranging from 0.0 to 1.0, set
			 * the `transform: rotate()` property according to the
			 * following equation: `-0.5 + 0.5x turns` The default
			 * properties below represent an x value of 0.
			 */

			.gauge--data {
			    -webkit-transform: rotate(-.50turn);
			       -moz-transform: rotate(-.50turn);
			        -ms-transform: rotate(-.50turn);
			         -o-transform: rotate(-.50turn);
			            transform: rotate(-.50turn);
			}
			.gauge--needle {
			    -webkit-transform: rotate(-.50turn);
			       -moz-transform: rotate(-.50turn);
			        -ms-transform: rotate(-.50turn);
			         -o-transform: rotate(-.50turn);
			            transform: rotate(-.50turn);
			}

		</style>
    </head>
    <body>
		<p>Hover over me</p>
    	<div class="gauge gauge__liveupdate" id="gauge">
        	<div class="gauge--container" id="gauge-container">
        		<div class="gauge--marker"></div>
        		<div class="gauge--background"></div>
        		<div class="gauge--center"></div>
        		<div class="gauge--data"></div>
        		<div class="gauge--needle"></div>
        	</div>
        	<div class="gauge--labels mdl-typography--headline">
            	<span class="gauge--label__low">No</span>
            	<span class="gauge--label__spacer"></span>
            	<span class="gauge--label__high">Yes</span>
        	</div>
    	</div>
		<script>
		
			// #### Gauge

			// The Gauge object encapsulates the behavior
			// of simple gauge. Most of the implementation
			// is in the CSS rules, but we do have a bit
			// of JavaScript to set or read the gauge value

			function Gauge(el) {

			    // ##### Private Properties and Attributes

			    var element,      // Containing element for the info component
			        data,         // `.gauge--data` element
			        needle,       // `.gauge--needle` element
			        value = 0.0,  // Current gauge value from 0 to 1
			        prop;         // Style for transform

			    // ##### Private Methods and Functions
    
			    var setElement = function(el) {
			        // Keep a reference to the various elements and sub-elements
			        element = el;
			        data = element.querySelector(".gauge--data");
			        needle = element.querySelector(".gauge--needle");
			    };
    
			    var setValue = function(x) {
			        value = x;
			        var turns = -0.5 + (x * 0.5);
			        data.style[prop] = "rotate(" + turns + "turn)";
			        needle.style[prop] = "rotate(" + turns + "turn)";
			    };

			    // ##### Object to be Returned

			    function exports() { };

			    // ##### Public API Methods

			    exports.element = function(el) {
			        if (!arguments.length) { return element; }
			        setElement(el);
			        return this;
			    };
    
			    exports.value = function(x) {
			        if (!arguments.length) { return value; }
			        setValue(x);
			        return this;
			    };

			    // ##### Initialization
    
			    var body = document.getElementsByTagName("body")[0];
			    ["webkitTransform", "mozTransform", "msTransform", "oTransform", "transform"].
			        forEach(function(p) {
			            if (typeof body.style[p] !== "undefined") { prop = p; }
			        }
			    );

			    if (arguments.length) {
			        setElement(el);
			    }

			    return exports;

			};

			var gauge = new Gauge(document.getElementById("gauge"));
			
			gauge.value(0.25);
			document.getElementById("gauge-container").addEventListener("mouseover", function() {
				gauge.value(0.75);
			});
			document.getElementById("gauge-container").addEventListener("mouseout", function() {
				gauge.value(0.25);
			});

		</script>
	</body>
</html>

README2.md

As a change of pace from complex visualizations, here's simple [Material Design](https://www.google.com/design/spec/material-design/introduction.html) gauge control implemented in pure CSS/HTML. The implementation includes an optional JavaScript component to change the gauge value dynamically. If you'd like to use the gauge on your web pages (it's open source), you can download it from [GitHub](https://github.com/sathomas/material-gauge), where you'll also find documentation on how to use it. In this post we'll walk through the implementation to understand how it works.

## Overall Structure

The gauge consists of several `<div>` elements layered on top of each other. Those layers are:
	
	1. `.gauge` The parent element for the entire component.
	2. `.gauge--container` The container is the outermost element for the gauge proper. All of the other layers are rendered within the container. 
	3. `.gauge--background` The background provides the "off" portion of the gauge. In this example it's a light grey/green in color.
	4. `.gauge--data` The data shows the data value for the gauge, dark green in this example.
	5. `.gauge--center` The center creates the center "cutout" for the gauge. It's white, so it doesn't show up explicitly.
	6. `.gauge--marker` The marker indicates the mid-point of the gauge to make it easy to distinguish positive from negative values. It's a thin white line.
	7. `.gauge--needle` The needle marks the gauge value with an orange line.
	
We'll take each of these layers one at a time and examine how they work.

> Note: The gauge also includes support for labelling the extreme values, "No" and "Yes" in the example. Those are built with standard CSS/HTML, however, so we won't consider them in this post.

## Parent Element

The parent element (with class `gauge`) defines the overall size of the gauge, and it has one CSS property that is crucial for the implementation. The property, `position: relative` establishes a _positioning context_ for all of the other HTML elements within it. This might be a bit confusing, because the `position: relative` rule doesn't affect the `.gauge` element itself. What it does do, however, is affect elements within the `.gauge`. More specifically, elements inside `.gauge` that have a `position: absolute` property are positioned _relative to their `.gauge` parent_, and **not** relative to the browser viewport.

## Gauge Container

The gauge container element (with class `gauge--container`) collects the individual parts of the gauge proper and centers the gauge horizontally on the page. It's the `transform: translateX(-50%)`, combined with a `left:50%`, that tells the browser to center the gauge. You can see the effect in the example below. The example adds a red border to the container to make it visible.

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width:300px;height:150px;margin:0;padding:0;position:absolute;left:50%;overflow:hidden;text-align:center;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);-o-transform:translateX(-50%);transform:translateX(-50%);border:1px solid #CA0000;">
</div>
</div>

## Gauge Background

The background element (with class `gauge--background`) shows the "off" part of the gauge. Coloring the "off" part is simply a matter of setting the background color of the `<div>`:
	
<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;">
</div>
</div>
</div>

Not only do we want to color the gauge, however; we also want to give it the rounded shape. To do that we'll use a CSS trick. It's a pretty common trick used on a lot of web pages, but perhaps a little surprising if you haven't seen it before: we use the `border-radius` property to turn a square into a circle. The CSS standard originally defined `border-radius` as a way to add rounded corners to rectangular HTML elements. If you define a radius size that's at least half of the size of a square, though, the entire squate becomes curved. That turns the square into a circle. Select the checkbox on the example below to see this effect in action.

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="position:relative;top:180px;display:table;text-align:center;width:100%;"><label for="cb1" style="font-size:14px;"><input type="checkbox" id="cb1" name="cb1"/> border-radius: 300px 300px 0 0;</label></div>
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div id="ex1" style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;-webkit-transition: all 3s ease-in-out; -moz-transition: all 3s ease-in-out; -ms-transition: all 3s ease-in-out; -o-transition: all 3s ease-in-out; transition: all 3s ease-in-out;">
</div>
</div>
</div>
<script>
document.getElementById("cb1").addEventListener("change",function(){document.getElementById("ex1").style.borderRadius = document.getElementById("cb1").checked ? "300px 300px 0 0" : "0"});
</script>

Notice that we're only setting a border radius on the top left and top right corners; both bottom corners remain square. That creates the desired semi-circle instead of a full circle.

## Gauge Data

The next layer is the "on" part of the gauge. This is the gauge data value. The starting point for the gauge data is the same as for the gauge background: a `<div>` whose `border-radius` property turns it into a semi-circle. The color, of course, differs.
	
<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#007979;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
</div>
</div>

So far our gauge is showing completely "full". What we want, however, is a gauge that shows a value somewhere between "empty" and "full." We'll do that by rotating the `.gauge--data` element. The CSS property that performs a rotation is `transform: rotate()`, but there's a catch: Normally, the rotation is about the center of the element. That won't work in our case; here's what happens if we try to use this approach to show a "half full" gauge. The red dot shows the center of rotation for the data element.

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.25turn);-moz-transform: rotate(-.25turn);-ms-transform: rotate(-.25turn);-o-transform:transform: rotate(-.25turn);"></div>
<div style="z-index:2;position:absolute;background-color:#CA0000;width:10px;height:10px;border-radius:10px;top:calc(50% - 5px);left:calc(50% - 5px);"></div>
</div>
</div>

_Ouch!_ That doesn't do the trick at all. Fortunately, there's a simple CSS property that changes the axis of rotation. By setting `transform-origin: center bottom;` we can rotate the data part of the gauge correctly.

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:170px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: visible;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.25turn);-moz-transform: rotate(-.25turn);-ms-transform: rotate(-.25turn);-o-transform:transform: rotate(-.25turn);-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;"></div>
<div style="z-index:2;position:absolute;background-color:#CA0000;width:10px;height:10px;border-radius:10px;top:calc(100% - 5px);left:calc(50% - 5px);"></div>
</div>
</div>

To complete the rotation of our data element, we need to calculate the appropriate value for the rotation. Fortunately, some very basic math is all that's required. For a "full" gauge, we don't want any rotation at all; that's a rotation of 0°. For an empty gauge, we rotate the data element half way around, or -180°. In-between values are just linear interpolations of those two extremes. You can see the effect in the following example by experimenting with the rotation value. 

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:170px;">
<div style="position:relative;top:330px;display:table;text-align:center;width:100%;font-size:16px;"><label for="in2">translate: rotate( </label><input type="number" id="in2" name="in2" value="0" min="-180" max="0" step="10" style="color:inherit;font-family: inherit;font-style: inherit;font-weight: inherit;width:4em;"/>deg)</div>
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: visible;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;">
</div>
<div id="ex2" style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;width: 300px; height: 150px;"></div>
<div style="z-index:2;position:absolute;background-color:#CA0000;width:10px;height:10px;border-radius:10px;top:calc(100% - 5px);left:calc(50% - 5px);"></div>
<div style="z-index:10;width:100%;height:150px;position:absolute;top:150px;background-color:rgba(255,255,255,0.25);"></div>
</div>
</div>
<script>
var prop,body = document.getElementsByTagName("body")[0];["webkitTransform", "mozTransform", "msTransform", "oTransform", "transform"].forEach(function(p) {if (typeof body.style[p] !== "undefined") {prop = p;}});
document.getElementById("in2").addEventListener("change",function(){document.getElementById("ex2").style[prop] = "rotate(" + document.getElementById("in2").value + "deg)";});
</script>

Now we've rotated the gauge data element correctly, but the entire `<div>` is showing, even the part below the gauge. Fixing that problem is a simple matter of adding `overflow:hidden;` to the gauge container:
	
<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.125turn);-moz-transform: rotate(-.125turn);-ms-transform: rotate(-.125turn);-o-transform:transform: rotate(-.125turn);-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;"></div>
</div>
</div>

## Gauge Center

Now we can transform the semi-circle into an arc. That's the job of the center element (of class `gauge--center`). It's just another semi-circle `<div>` with a white color that sits on top of the gauge. The white color has the effect of "cutting out" part of the semi-circle.

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.25turn);-moz-transform: rotate(-.25turn);-ms-transform: rotate(-.25turn);-o-transform:transform: rotate(-.25turn);-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;"></div>
<div style="z-index:2;position:absolute;background-color:white;width: 180px; height: 90px; top: 60px; margin-left: 60px;border-radius: 300px 300px 0 0;"></div>
</div>
</div>

## Gauge Marker

Now we're left with a few easy bits to add to make the component complete. The first of those is a marker to indicate the half way point for the guage. That's nothing more than a thin, positioned `<div>`

<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.125turn);-moz-transform: rotate(-.125turn);-ms-transform: rotate(-.125turn);-o-transform:transform: rotate(-.125turn);-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;"></div>
<div style="z-index:2;position:absolute;background-color:white;width: 180px; height: 90px; top: 60px; margin-left: 60px;border-radius: 300px 300px 0 0;"></div>
<div style="height: 150px; left: 149.5px;z-index: 3;background-color: #fff;position: absolute;width: 1px;"></div>
</div>
</div>

## Gauge Needle

The final addition is the needle. Like the marker, it's a simple thin `<div>` element. To match the gauge value, though, we need to rotate it, just as we rotated the data element.
	
<div style="position:relative;height:calc(150px + 3em);padding-top:20px;padding-bottom:20px;">
<div style="width: 300px;height:150px;margin:0;padding:0;position: absolute;left: 50%;overflow: hidden;text-align: center;-webkit-transform: translateX(-50%);-moz-transform: translateX(-50%);-ms-transform: translateX(-50%);-o-transform: translateX(-50%);transform: translateX(-50%)">
<div style="z-index:0;position:absolute;background-color:#C0D3D3;top:0;width:300px;height:150px;border-radius:300px 300px 0 0;"></div>
<div style="z-index: 1;position: absolute;background-color: #007979;margin-left: auto;margin-right: auto;border-radius: 300px 300px 0 0;width: 300px; height: 150px;-webkit-transform: rotate(-.125turn);-moz-transform: rotate(-.125turn);-ms-transform: rotate(-.125turn);-o-transform:transform: rotate(-.125turn);-webkit-transform-origin: center bottom;-moz-transform-origin: center bottom;-ms-transform-origin: center bottom;-o-transform-origin: center bottom;transform-origin: center bottom;"></div>
<div style="z-index:2;position:absolute;background-color:white;width: 180px; height: 90px; top: 60px; margin-left: 60px;border-radius: 300px 300px 0 0;"></div>
<div style="height: 150px; left: 149.5px;z-index: 3;background-color: #fff;position: absolute;width: 1px;"></div>
<div style="-webkit-transform: rotate(-.125turn);-moz-transform: rotate(-.125turn);-ms-transform: rotate(-.125turn);-o-transform:transform: rotate(-.125turn);z-index: 4;background-color: #F77C15;height: 3px;position: absolute;-webkit-transform-origin: left center;-moz-transform-origin: left center;-ms-transform-origin: left center;-o-transform-origin: left center;transform-origin: left center;left: 150px; top: 147px; width: 150px;"></div>
</div>
</div>

## Conclusion

That's it. With a few bits of CSS and HTML we've created a nice gauge in the Material Design style. Let me know via [Twitter](https://twitter.com/jsdatavis) if you're interested in more posts along these lines.

<script src="http://jsDataV.is/img/thumbnails/material-gauge-post.js"></script>

script.lnk

/img/thumbnails/material-gauge-post.js

thumbnail.lnk

http://jsdatav.is/img/thumbnails/material-gauge.png