Across the web, you’ll see a range of sites that feature calculators for working out things like loan repayments, mortgage rates, tax, insurance, and more. Until now, we’ve had no way of semantically marking up the result of those calculations. Enter: the <output> element! In this article, we’ll show you <output> and some related JavaScript tricks. Let’s get cracking.
The Definition #
The <output> element, new in HTML5, is used in forms. The WHATWG HTML specification describes <output> very simply:
The output element represents the result of a calculation.
Along with the standard global attributes, <output> also accepts the following:
for- A space-separated list containing the IDs of the elements whose values went into the calculation.
form- Associates the
<output>element with its form owner. The value must be the ID of a form in the same document. This allows you to place an<output>element outside of the<form>with which it is associated. name- The name of the element.
Implementing <output> #
We’ll start by creating a simple example that adds two whole numbers together (Figure 1). We’ll use the new-in-HTML5 number input type and the parseInt JavaScript function to convert the input strings to integers:
<form onsubmit="return false" oninput="o.value = parseInt(a.value) + parseInt(b.value)">
<input name="a" type="number" step="any"> +
<input name="b" type="number" step="any"> =
<output name="o"></output>
</form>
Notice that we’re using the now-standard oninput event, which has replaced the deprecated onforminput event. Daniel Friesen has written a detailed article on the background and current support of oninput. oninput isn’t supported in IE8 and below, and its IE9 support is a little flaky, but you can work around these problems using the html5Widgets polyfill.
See a live example of the code in Figure 1.
As you’d expect, if you only enter a single value, the function returns NaN. It’s effectively trying to add a number and an undefined value, and 1 + undefined = undefined.
Using the for Attribute #
Let’s build on the previous example and add the for attribute to the <output> (Figure 2). We need to add IDs to each of the associated <input>s, just as we would with the for attribute on a <label>:
<form onsubmit="return false" oninput="o.value = parseInt(a.value) + parseInt(b.value)">
<input name="a" id="a" type="number" step="any"> +
<input name="b" id="b" type="number" step="any"> =
<output name="o" for="a b"></output>
</form>
for attribute on the <output> elementThe valueAsNumber Property #
HTML5 has also introduced the valueAsNumber property of JavaScript input objects (specifically those of type number, date, and range). This returns the value as a number rather than as a string, meaning we no longer need to use parseInt or parseFloat, and the + operator adds rather than concatenates:
<form onsubmit="return false" oninput="o.value = a.valueAsNumber + b.valueAsNumber">
<input name="a" id="a" type="number" step="any"> +
<input name="b" id="b" type="number" step="any"> =
<output name="o" for="a b"></output>
</form>
valueAsNumber property for retrieving a numeric value from an inputInvoicing Calculator: An In-depth Example with Fallbacks #
For a more realistic example, let’s create an invoicing calculator that multiplies the number of hours by the hourly rate and adds tax to give an overall total (Figure 4):
<form onsubmit="return false" oninput="amount.value = (hours.valueAsNumber * rate.valueAsNumber) + ((hours.valueAsNumber * rate.valueAsNumber) * vat.valueAsNumber)">
<legend>Invoice</legend>
<p><label for="hours">Number of hours</label>
<input type="number" min="0" id="hours" name="hours"></p>
<p><label for="rate">Rate</label>
<span>£</span><input type="number" min="0" id="rate" name="rate"></p>
<p><label for="vat">VAT</label>
<input type="number" min="0" id="vat" value="0.20" name="vat"></p>
<p>Total: <strong>£<output name="amount" for="hours rate vat">0</output></strong></p>
</form>
output elementSee a live example of the code in Figure 4.
Nothing too complicated going on there. In fact, the scripting is so simple that even I can do it
A Mildly Controversial Example Using <input type="range"> #
HTML5 also introduces the range input type, which renders as a slider control in supporting browsers. With this input type, a user can enter an approximate value within a given range without having to be completely precise or directly type a numeric value. For cross browser compatibility, see Remy’s input range polyfill.
While researching this article, I found a number of examples using the <output> element in conjunction with <input type="range"> as shown in Figure 5:
<form onsubmit="return false" oninput="level.value = flevel.valueAsNumber">
<label for="flying">Flying Skill Level</label>
<input name="flevel" id="flying" type="range" min="0" max="100" value="0">
<output for="flying" name="level">0</output>/100
</form>
<input type="range"> with the <output> elementSee a live example of the code in Figure 5.
Using <output> to show the current value to the user seems like a perfectly reasonable use case to me, but it isn’t the result of a calculation
as the spec describes. I haven’t spoken directly to Hixie about this, but a couple of people on the IRC channel seemed to agree with, so I filed a bug report to request the definition be amended. I’ll update this article if something changes.
Browser Support and Polyfills #
The good news is that all modern browsers support the <output> element to some extent. The bad news is that there are still a few gotchas.
| Browser | Support |
|---|---|
| Chrome | 13+ |
| Safari | 5.1+ |
| Firefox* | 6+ |
| Opera | 9.20+ |
| Internet Explorer | 10+ |
* Firefox does support the <output> element and the oninput event, but it doesn’t support the valueAsNumber property.
All the examples we’ve seen so far should work perfectly in Opera 11.5+, Safari 5.1+, and Chrome 13+. IE, as you might expect, is lagging somewhat, but support for <output> is in IE10 Platform Preview 2, and support for oninput is already in IE9.
In order to work around this in our simple examples, we’ll need to revert to the tried-and-trusted getElementByID and parseFloat (Figure 6):
<form onsubmit="return false" oninput="document.getElementById('o').innerHTML = parseFloat(document.getElementById('a').value) + parseFloat(document.getElementById('b').value)">
<input name="a" id="a" type="number" step="any"> +
<input name="b" id="b" type="number" step="any"> =
<output name="o" id="o" for="a b"></output>
</form>
getElementById to support older browsersSee a live example of the code in Figure 6.
While this isn’t ideal, it’s workable until those less-capable browsers die a slow and painful death. Alternatively, you can use polyfills to plug the gaps.
To check support in your current browser, open up Mike Taylor’s support test page.
To support less-capable browsers, there are polyfills such as HTML5 Widgets created by Zoltan “Du Lac” Hawryluk. Zoltan talks you through the process in this detailed article on creating cross browser forms using html5Widgets.Polyfills #
Summary #
You probably won’t find yourself using the <output> element all the time, but it’s useful in a whole host of situations. Calculating values on financial sites spring to mind, or outputting the current mouse position, or perhaps the goal difference in a table of sports teams. What other use cases can you think of for <output>? Let us know in the comments!
Related reading #
- WHATWG HTML Specification for
<output> - W3C Elements Wiki Page for
<output> - Wufoo HTML5 Forms Tests for
<output> - Mozilla Developer Network docs on
<output> - Is
onforminputDeprecated in HTML5 Forms? (And Why Should I Care Anyways?) by Zoltan Hawryluk - A HTML5 Browser Maze:
oninputSupport by Daniel Friessen - Fixing
oninputin IE Using html5Widgets by Zoltan Hawryluk

18 Responses on the article “The output element”
In Figure 6 you specify the id of the inputs twice (2nd and last attributes).
Great article though, thank you.
@Bernhard – So I did, thanks. Have updated it now.
@Richard Clark
I’m the creator of webshims lib and I’m wondering, why you haven’t added the forms feature implementation of webshims lib to the list of possible polyfills.
If found something strange or you dislike, please let me know. I’m always trying to make webshims lib better.
Does the
foratttribute have any behavior by default?What do we do with a web site in, say, German or Swedish, where the input and the output should use a decimal comma instead of a decimal point (the same goes for many, if not most, languages)? How do we use HTML5 in such cases?
@Bertil Wennergren
The value, which is shown to the user can be localized by the browser. Chrome is doing this for example. And you can simply change/transform the output to a locale you want.
I made a fiddle, which showcases the use of “toLocaleString”:
http://jsfiddle.net/trixta/Zw37n/
“The value, which is shown to the user can be localized by the browser. Chrome is doing this for example.”
For “output” elements or for “input[type=number]” or for both?
Exactly what does Chrome do now with “input[type=number]” and “output” in, say, an English web page in a German browser, or a German web page in an English browser? Does the decimal character depend on the language of the web page or the language of the browser? Or are there perhaps user settings for this?
only input[type=number] is localized to the language of the browser. so in a german browser the user will see 1,1 and in an english browser 1.1, but submit-data is still 1.1 in all browsers.
output simply shows what the developer puts into. it has no format restrictions. so you can do something like this:
$(‘output’).prop(‘value’, “”+$.prop( inputElement, ‘valueAsNumber’).replace(‘.’, ‘,’));
“output simply shows what the developer puts into”
Should the value of an output element be submitted along with all the outher form data? The specs don’t seem to address that clearly, but an output element can have a name attribute, and that seems to indicate that its value should be submitted. If so, then it does matter how decimal separators are interpreted. What should be submitted if the value “1,234″ is put into an output element? And what would the valueAsNumber property be?
@Bertil – The submittable elements are button, input, keygen, object, select and textarea. So not the output element. See
http://dev.w3.org/html5/spec/forms.html#category-submit
Value “any” for “step” attribute isn’t working correctly in Safari for input type number…
39/100 is not so much the output of a computation, but the computation itself
I think you could make a case that the output with the range is actually the result of a division (computing percentages)
I guess should show not only “result of a calculation” but result at all! Then I see lots of cases we can use element. For example real-time updating comment preview or the preview of cropped image when you are changing your userpic.
I guess <input> should show not only “result of a calculation” but result at all! Then I see lots of cases we can use <input> element. For example real-time updating comment preview or the preview of cropped image when you are changing your userpic.
Definitely a feature for the future (hey it rhymed
)
Thanks Richard. One question, related to PHP, can the $_POST array handle the output element?
“One question, related to PHP, can the $_POST array handle the output element?”
If the value of an output element is not submitted at all (as it seems), then there is nothing to handle.
If on the other hand it does get submitted, then there is no way for PHP to tell if the value came from an output element, from an input element of from some other element (or indeed from any kind of HTML element at all). It will simply be there in the $_POST array (or $_GET array) with its name and its value. So PHP can indeed handle such submissions.
Many thanks Bertil. I don’t know why I was under the impression that the $_POST or $_GET array were conditioned by input tags that are commonly supported in HTML (radio, select, text, etc, etc) but now that I think of it, what matters is actually the name attribute for the array to recognize it.
Looking forward to some test cross browser styling with this. Good article cheers.
Join the discussion.