The following is a guest post by Pankaj Parashar. Pankaj has written here before, last time about the progress
element. Fitting indeed then to write again about the very related meter
element. They are different both functionally and semantically, so read on!
As defined by W3C,
The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate. This is also known as a gauge.
If you are like me, the above spec wouldn’t make much sense until we dive deep into the implementation. So let’s just start with a basic markup for the meter element:
<meter></meter>
Similar to its sibling – the progress
element – a meter element must also have both a start tag (<meter>
) and an end tag (</meter>
). This becomes very useful when we devise a robust fallback technique for older browsers that do not support the meter element, later in this article.
Content model
The meter element uses the phrasing content model which means it can contain the text of the document, along with the elements that mark up that text, but there must be no (additional) meter element among its descendants.
Attributes
Apart from the global attributes, the meter element can have 6 more attributes.
value
– A floating point number that represents the current value of the measured range. This must be between the min
and the max
value (if specified).
min
– Indicates the lower bound of the measured range. This must be less than the max
value (if specified). If unspecified, the minimum value is 0.
max
– Indicates the upper bound of the measured range. This must be greater than the min
value (if specified). If unspecified, the maximum value is 1.0.
low
– It represents the upper bound of the low end of the measured range. This must be greater than the min
attribute, but less than the high
and max
value (if specified). If unspecified, or if less than the minimum value, the low
value is equal to the min
value.
high
– It represents the lower bound of the high end of the measured range. This must be less than the max
attribute, but greater than the low
and min
value (if specified). If unspecified, or if greater than the max
value, the high
value is equal to the max
value.
optimum
– This attribute indicates the optimum value and must be within the range of min
and max
values. When used with the low
and high
attribute, it indicates the preferred zone for a given range. For example:
-
min ≤ optimum ≤ low
– If the optimum value is between themin
and thelow
values, then the lower range is considered to be the preferred zone. -
high ≤ optimum ≤ max
– If the optimum value is between thehigh
and themax
values, then the upper range is considered to be the preferred zone.
A meter with everything would look like:
<meter min="0" low="10" optimum="50" high="90" max="100"></meter>
Rules of thumb
- All the above mentioned attributes may be floating point numbers e.g. 12, -8, 3.625
- Based on the definition of each attribute the following inequalities become true,
min ≤ value ≤ max
min ≤ low ≤ high ≤ max
(if low/high specified)min ≤ optimum ≤ max
(if optimum specified)
- There is no explicit way to specify units in the meter element, but the authors are encouraged to specify the units using the title attribute. For example,
<meter max="256" value="120" title="GB">120GB out of 256GB are used</meter>
Do not use meter element to…
- indicate the progress completion of a task (use
progress
element instead). - represent a scalar value of an arbitrary range — for example, to report a weight, or height of a person.
Experiment #1 – Different states of meter element
This experiment shows the various states of the meter element under different combination of input values for each attribute. Feel free to edit the attribute values of the main code to tweak the meter gauge ouput.
See the Pen HTML5 Meter Element by Pankaj Parashar (@pankajparashar) on CodePen
Experiment #2 – OSX style disk usage
In this experiment, we’ll try and simulate the appearance of the disk usage panel in OS X using the meter
element and then style it as cross-browser as possible.
Populating internal attributes of our meter tag with the known set of input values.
- Total size of the disk – 120.47GB (our
max
attribute) - Current disk usage – 55.93GB (our
value
attribute) - Minimum disk size – 0 (our
min
attribute, not required as the default value is 0) - Unit – GB (our
title
attribute that specifies the unit)
<meter max="120" value="55.93" title="GB"></meter>
Before we apply any CSS, the meter gauge looks like this in Chrome 30 on OX X 10.9.
meter
tag for older browsers, we’ll keep it blank for now to add the fallback content later in this article to support them.This is pretty much all that we can do in HTML as rest of the work is done by CSS. At this stage let’s not worry about the fallback techniques for supporting older browsers that don’t understand the meter
element.
Styling the meter element
Just like any other element, we can define dimensions by specifying width
and height
for meter.
meter {
width: 500px;
height: 25px;
}
This is where things become interesting because generally most of the A-grade browsers provide separate pseudo classes to style the meter element. Although Opera moving to Blink leaves us with less browsers to care for. At this stage, we don’t really have to know about which versions of each browser support the meter
element, because our fallback technique will take care of the rest. We classify them as follows:
- Webkit/Blink
- Firefox
- Internet Explorer
1. Webkit/Blink (Chrome/Safari/Opera/iOS)
On inspecting the meter element via Chrome Developer Tools, we can reverse-engineer the implementation of the spec in webkit browsers.
In addition, the User-Agent stylesheet of WebKit provides a wealth of information on how you can use various pseudo classes to access different states of the meter element.
Pseudo class | Description |
---|---|
-webkit-meter-inner-element |
Additional markup to render the meter element as read-only. |
-webkit-meter-bar |
Container of the meter gauge that holds the value. |
-webkit-meter-optimum-value |
The current value of the meter element and is by default green when the value attribute falls inside the low-high range. |
-webkit-meter-suboptimum-value |
Gives a yellow color to the meter element when the value attribute falls outside the low-high range. |
-webkit-meter-even-less-good-value |
Gives a red color to the meter element when the value and the optimum attributes fall outside the low-high range but in opposite zones. For example, value < low < high < optimum or value > high > low > optimum |
First, let’s start by resetting the default appearance of the meter gauge by using -webkit-appearence: none;
meter {
width: 500px;
height: 25px;
-webkit-appearance: none; /* Reset appearance */
border: 1px solid #ccc;
border-radius: 3px;
}
For this experiment, we will only be using -webkit-meter-bar
(to style the container) and -webkit-meter-optimum-value
(to style the value) pseudo classes. Each color in background linear gradient represents the space consumed by the sub-categories like – Apps, Movies, Photos etc.
meter::-webkit-meter-bar {
background: none; /* Required to get rid of the default background property */
background-color: whiteSmoke;
box-shadow: 0 5px 5px -5px #333 inset;
}
meter::-webkit-meter-optimum-value {
box-shadow: 0 5px 5px -5px #999 inset;
background-image: linear-gradient(
90deg,
#8bcf69 5%,
#e6d450 5%,
#e6d450 15%,
#f28f68 15%,
#f28f68 55%,
#cf82bf 55%,
#cf82bf 95%,
#719fd1 95%,
#719fd1 100%
);
background-size: 100% 100%;
}
CSS3 Transition/Animation
WebKit browsers support both transition and animation on the meter
element. Just for the sake of testing, I experimented by changing the width of the value(on :hover
) using transitions and animating the background position of the container using keyframes
. Although not applicable for practical usage, both the experiments turned out pretty well on all three browsers.
meter::-webkit-meter-optimum-value {
-webkit-transition: width .5s;
}
meter::-webkit-meter-optimum-value:hover {
/* Reset each sub-category to 20% */
background-image: linear-gradient(
90deg,
#8bcf69 20%,
#e6d450 20%,
#e6d450 40%,
#f28f68 40%,
#f28f68 60%,
#cf82bf 60%,
#cf82bf 80%,
#719fd1 80%,
#719fd1 100%
);
transition: width .5s;
width: 100% !important; /* !important required. to override the inline styles in WebKit. */
}
meter::-webkit-meter-bar {
/* Let's animate this */
animation: animate-stripes 5s linear infinite;
background-image:
linear-gradient(
135deg,
transparent,
transparent 33%,
rgba(0, 0, 0, 0.1) 33%,
rgba(0, 0, 0, 0.1) 66%,
transparent 66%
);
background-size: 50px 25px;
}
@keyframes animate-stripes {
to { background-position: -50px 0; }
}
Pseudo Elements
At the time of writing, only webkit browsers support pseudo elements on meter gauge. For this experiment, we could use the pseudo elements to display the meta information like HD Name, Free space right above the meter gauge.
meter {
margin: 5em;
position: relative;
}
meter::before {
content: 'Macintosh HD';
position: absolute;
top: -100%;
}
meter::after {
content: '64.54 GB free out of 120.47 GB';
position: absolute;
top: -100%;
right: 0;
}
Apart from WebKit, the support for pseudo elements in other browsers is non-existent. Hence, there is no good reason to embed content inside pseudo elements, at least for now.
2. Firefox
Similar to WebKit, Firefox uses -moz-appearence: meterbar
to paint the meter gauge. We can get rid of the default bevel and emboss by resetting it to none
.
meter {
/* Reset the default appearence */
-moz-appearance: none;
width: 550px;
height: 25px;
}
Firefox is shipped with a wholesome list of pseudo classes to style different states of the meter gauge. The snapshot below has been grabbed from the forms.css
file that can be accessed from inside Firebug.
Pseudo class | Description |
---|---|
-moz-meter-bar |
Represents the current value of the meter gauge that can be used to style the properties of the meter gauge value. |
-moz-meter-optimum |
It gives a green color to the meter element when the value attribute falls inside the low-high range. |
-moz-meter-sub-optimum |
It gives a yellow color to the meter element when the value attribute falls outside the low-high range. |
-moz-meter-sub-sub-optimum |
It gives a red color to the meter element when the value and the optimum attributes fall outside the low-high range but in opposite zones. For example, value < low < high < optimum or value > high > low > optimum |
For this experiment, we will only use ::-moz-meter-bar
to style the background of the meter gauge value.
meter::-moz-meter-bar {
box-shadow: 0 5px 5px -5px #999 inset;
background-image: linear-gradient(
90deg,
#8bcf69 5%,
#e6d450 5%,
#e6d450 15%,
#f28f68 15%,
#f28f68 55%,
#cf82bf 55%,
#cf82bf 95%,
#719fd1 95%,
#719fd1 100%
);
background-size: 100% 100%;
}
Interestingly, in Firefox you can style the background of the container using the meter
selector itself.
meter {
/* Firefox */
background: none; /* Required to get rid of the default background property */
background-color: whiteSmoke;
box-shadow: 0 5px 5px -5px #333 inset;
}
Firefox doesn’t support ::before
and ::after
pseudo elements on the meter gauge. The support for CSS3 transitions and animation is a bit shaky as well. Hence, there is no good reason to use them until the behavior becomes consistent across browsers.
3. Internet Explorer
To my knowledge, no stable version of Internet Explorer supports the meter element. Even the Modernizr test suite failed to detect meter in IE11 preview on Windows 8.1. This perhaps leaves us only with the fallback approaches that will be discussed in the next section.
if ('value' in document.createElement('meter')) {
alert("Meter element is supported");
} else {
alert("Meter element Not supported");
}
What about browsers that don’t support meter?
Can I Use (and simple testing) reports the meter gauge is natively supported in: Firefox 16+, Opera 11+, Chrome, Safari 6+. Internet Explorer, however offers no support what-so-ever for any version. If you want to make meter
element work in older browsers, then you’ve got two options:
1. Polyfill
Randy Peterman has written a polyfill that makes meter element work in older browsers (especially IE). During my cross-browser testing, I found that the polyfill works for all IE browsers down to IE6! which makes it a good candidate for usage in production.
2. HTML fallback
This is my preferred (no-JS) approach. It makes use of a common technique that was also discussed in my previous article for CSS-Tricks on the HTML5 progress element.
<meter value="55.93" min="0" max="120.47" title="GB">
<div class="meter-gauge">
<span style="width: 46.42%;">Disk Usage - 55.93GB out of 120GB</span>
</div>
</meter>
The idea is to simulate the appearance of a meter gauge using div
and span
inside the meter tag. Modern browsers that support meter will ignore the content within the tag. Older browsers that cannot render the meter element will ignore the tag and render the markup inside it.
.meter-gauge {
border: 1px solid #ccc;
border-radius: 3px;
background-color: whiteSmoke;
box-shadow: 0 5px 5px -5px #333 inset;
width: 550px;
height: 25px;
display: block;
}
.meter-gauge > span {
height: inherit;
box-shadow: 0 5px 5px -5px #999 inset;
background-color: blue;
background-image: linear-gradient(
90deg,
#8bcf69 5%,
#e6d450 5%,
#e6d450 15%,
#f28f68 15%,
#f28f68 55%,
#cf82bf 55%,
#cf82bf 95%,
#719fd1 95%,
#719fd1 100%
);
background-size: 100% 100%;
display: block;
text-indent: -9999px;
}
It is fairly common to use both the techniques in conjunction and it is perfectly safe for usage in production sites. The demo should run fine for all the browsers including Internet Explorer (down to IE6!). The meter gauge color is blue in all the versions of Internet Explorer. Opera 11 and 12 doesn’t permit changing the color of the meter gauge. Hence, it shows the default green color. The demo also uses some additional markup to display the disk usage of each sub-category like Apps, Movies, Photos etc.
See the Pen OSX-style Disk Usage by Pankaj Parashar (@pankajparashar) on CodePen
More Resources
- Official W3C Spec for meter
- MDN docs for meter
- HTMl5Doctor: Measure up with the meter tag
Thanks Pankaj and Chris (of course). Awesome post, took me a while to read it. Thank you!
Wow my that’s so cool. Thanks for posting this!
I needed this the other day while working on the CSSOff! I had done a search on this site and only found
<progress>
. You do a much better job of explaining how to style than any other site I was able to find.This is all nice and good but I think this tag is totally unnecessary.
I fear we may be overengineering this one.
actually i kinda agree with you…
I don’t know how widely useful it would be, but I have a specific application for which this tag would be perfect.
I have a site which uses horizontal bar charts to reflect a score, and those bars look very similar to the default appearance of this tag. The scores are between 1 and 10, scores below 4.5 are considered low, scores above 7.5 are considered high and 5.5 is the optimum. It’s a perfect fit for this tag.
At the moment I am producing the bars with SVG, which works and looks fine. However if you look at the HTML, all you see is a bunch of meaningless SVG drawing lines and polygons. With this tag, you would see a perfect semantic representation of the chart. That has implications for accessibility at the very least.
I would use it but for the lack of browser support, but I can see it being used down the track for sure.
The scenario that DarrenM described is a perfect use-case for the meter element.
@DarrenM – I don’t think you should be discouraged with the lack of browser support as the fallback technique is quite robust and doesn’t add bunch of meaningless tags to the HTML (like SVG). Hope you find it useful!
for Case 16
<meter low=”.25″ optimum=”.85″ high=”.75″ value=”.5″></meter>
What’s a scenario where optimum would be greater than high? And why does meter turn yellow if it’s still in between low and high? is it because it’s less than optimum?
Thanks, really deep article.
For Case 16 –
value
is between the low-high range but theoptimum
value is between the high-max range (default value of max is 1.0), which means that the upper range is considered to be the preferred zone.Now since the
value
(.5) doesn’t fall in theoptimum
preferred zone (.85 – 1.0), the color of the meter gauge changes to yellow. This state has been documented in the article under Attributes section.I can’t think of practical scenarios where this would be applicable, but the idea was to elaborate on all the possibilities defined by the spec :-)
ok thx, I forgot about “max range”
Hello,
Thanks for this interesting post!
I don’t understand why you say “Do not use meter to represent a scalar value of an arbitrary range — for example, to report a weight, or height of a person.” as it seems perfect to me for that usage. Am I missing something?
What would your max value be for weight or height? His example, disk usage, shows a value out of a maximum space available, which is why it works.
Well, I guess I would choose an arbitrary value. If I’m a t-shirt seller, this could be 2,20 meter representing the max t-shirt’s size I have. But if i’m a pollster, i’d probably choose the max in guiness book, let’s say about 3 meters.
Same thing if I want to represent someone with a 220gb hard drive and another guy with a 300gb one. In every case, that’s right, we have to fix a max value.
That’s valid argument. But I think you are still using an arbitrary number to decide on a maximum value.
Although the meter tag would correctly represent this information but that doesn’t sit well with the overall semantics and the real intention of introducing the meter tag.
Ok, I see what you mean.
Practically, as each case is different, the dev will have to decide if it seems relevant to present his data with meter (and a max fixed by him).
Thanks!
I think it would depend on the application. If you conducted a survey of the heights of people in your workplace, then you would have a max and min value when you report it. It would make perfect sense to use the meter element to reflect that because you can display where a person’s height sits within the sample.
The high, low and optimum attributes are optional. However you might decide that anyone outside two standard deviations from the mean is either low or high and you might want to reflect that for some (preferably non-discriminatory) reason. The optimum height might be short enough to walk through the tea room door without bumping your head but tall enough to reach things on the top shelf without needing a step :)
I think the point is that the meter element needs to have known upper and lower bounds to provide a context for the value being reported. It can’t really be used to reflect the number of red cars you saw yesterday, but it can be used to express how many of the cars you saw yesterday were red.
Exactly! It makes sense to represent a value if there are min (in most cases 0) and max values set as bounds.
It doesn’t make sense to represent a stand-alone value (equal to the max, as there is only one value) like for example the weight of a single person. I now understand what Pankaj was meaning in the initial sentence. Thanks.
Nice article, thanks. :) Just a small correction: I guess the second
-moz-meter-sub-optimum
in the table should be-moz-meter-sub-sub-optimum
.Yup you are right! I’ll try and get this changed with Chris’s help.
got it.
Can someone make a tutorial to use the new html5 slider with javascript
Give me an explanation about this sentence: “It represents the upper bound of the low end of the measured range.”
Looks better if you don’t change the ratios of the gradient while you’re resizing.
Like this.
I think he was trying to make the colors match up with the legend at the bottom, but I agree, yours is definitely better (but I fail to understand why the expansion is necessary to begin with).
The expansion on
:hover
thing is just a basic idea to test CSS3 transitions on themeter
tag. As I said in the article, there is no real meaning behind these experiments. I just wanted to test the different possibilities.But @Tal Ben-Ari is right, the idea was to align the width of each gradient with the legend below. But you can go with whatever approach that suits you the best :-)
Nice write-up. I’ll definitely keep this link for reference. I view meter as a bit arcane, perhaps useful in specialized applications (like a downloader), but it’s part of the spec so we should keep an eye on it.