HTML5 introduced several new tags, one of my favorites being <meter>, which is used to indicate scalar measurements. However, most browsers won’t do anything fancy with a <meter>.
But for everyone using another browser, we can easily fix that with a little CSS and JavaScript. Basically, we’re going to display each <meter> as a block element, and then insert a <div> element, whose size is determined by the <meter>‘s value attribute.
-
First, decide how you want your <meter> styled. I opted to use the CSS system colors for a native look and feel, and -webkit-gradient to give it a nice sheen in Chrome and Safari.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48meter {
/* You can customize the following. */
background-color: appworkspace;
border: thin inset menu;
height: 1em;
width: 100%;
/* Leave the rest alone. */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
clear: both;
display: block;
overflow: hidden;
position: relative;
}
/* Style the inner bar. */
meter > div {
/* You can customize the following. */
background-color: highlight;
background-image: -webkit-gradient(linear, 0% 0%, 90% 0%,
from(rgb(28, 155, 91)), to(rgb(108, 255, 108)));
box-shadow: 2px 0 8px grey;
-moz-box-shadow: 2px 0 8px grey;
-webkit-box-shadow: 2px 0 8px grey;
/* Okay, that's enough customizing for now. */
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
float: none !important;
height: 100%;
margin-left: 0 !important;
min-width: 1px;
position: relative;
bottom: 0;
left: 0;
top: 0;
text-overflow: none !important;
vertical-align: inherit !important;
}
meter.toohigh > div, meter.toolow > div {
background-color: red !important;
background-image: -webkit-gradient(linear, 0% 0%, 90% 0%,
from(rgb(155, 28, 91)), to(rgb(255,108,108))) !important;
} -
Next, we’re going to use JavaScript to create the bar inside the <meter>. I opted to use the MooTools framework, but if you’re more adept with another framework, it should be fairly simple to port or rewrite my code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50function updateMeter(m) {
// Does this meter already have a bar?
// If not, make one. Otherwise, use the existing one.
if (m.getChildren().length == 0) {
bar = new Element("div");
} else {
bar = m.getChildren()[0];
}
// Set the bar's width to be a percentage of the meter, based
// on the min and max values.
width = m.getStyle("width").replace("px","").toInt();
if (m.get("min")) {
width *= m.get("data-value") / (m.get("max") - m.get("min");
} else {
width *= m.get("data-value") / m.get("max");
}
bar.setStyle("width", Math.ceil(width));
// If we've set the high attribute, and the meter's value is
// greater than high, give it the class toohigh.
if (m.get("high")
&& m.get("data-value").toInt() >= m.get("high").toInt())
{
m.addClass("toohigh");
}
// Same thing, but with the low value.
else if (m.get("low")
&& m.get("data-value").toInt() < = m.get("low").toInt())
{
m.addClass("toolow");
} else {
m.removeClass("toolow");
m.removeClass("toohigh");
}
// A meter should contain a description of the measurement
// inside of it. Move that into the tooltip.
m.set("title", m.get("text"));
// Inject the bar.
if (m.getChildren().length == 0) {
m.empty().grab(bar);
}
}
window.addEvent("domready",function(){
$$("meter").each(function(m){
updateMeter(m);
});
}); -
Finally, mark up your <meter> tags. Your <meter> must have at least the value and max attributes set.
(Note that due to a strange bug in MooTools, I had to duplicate the value attribute as a data-value attribute. It’s still legal HTML5, though. If you choose not to use MooTools, you can omit the data-values.)
1
2
3<meter min="0" max="100" low="10" value="40" data-value="40">
This meter is set to 40%, thankfully; 10% is too low!
</meter>
To demonstrate this, I needed a good real-world data set. What’s more real world than my own Web server? With a little bit of PHP, I was able to whip together a little server status widget that shows CPU load and memory and swap usage.
Now that’s cool. Google Chrome 6 will do this to all <meter> tags automatically, so you won’t need JavaScript; however, this trick will still work, and (as always) you can still use CSS to override Chrome 6′s stylistic choices.
