The HTML5 meter Element

Guest Author //

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 the min and the low values, then the lower range is considered to be the preferred zone.
  • high ≤ optimum ≤ max - If the optimum value is between the high and the max 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

  1. All the above mentioned attributes may be floating point numbers e.g. 12, -8, 3.625
  2. 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)
  3. 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...

  1. indicate the progress completion of a task (use progress element instead).
  2. 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.

Default appearance of the meter element in Chrome 30 on OS X 10.9
Although the spec recommends including a textual representation of the gauge's state inside the 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.

Inspect element on Chrome DevTools

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.

User-Agent stylesheet of WebKit browsers
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.

WebKit pseudo classes on the meter element
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;
}

Output after styling the background container
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%;
}

Output after styling the meter gauge value

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. */
}

CSS3 Transitions in action (:hover)
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; }
}

CSS3 Animated background stripes in action

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;
}

Pseudo elements in action

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

Firebug screenshot (on inspecting the meter element in Firefox 25)

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.

[forms.css] snapshot for meter element in Firefox 25
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