The Output Element

Avatar of Robin Rendle
Robin Rendle on

Last night I was rooting around in the cellars of a particularly large codebase and stumbled upon our normalize.css which makes sure that all of our markup renders in a similar way across different browsers. I gave it a quick skim and found styles for a rather peculiar element called <output> that I’d never seen or even heard of before.

According to MDN, it “represents the result of a calculation or user action” typically used in forms. And rather embarrassingly for me, it isn’t a new and fancy addition to the spec since Chris used it in a post all the way back in 2011.

But regardless! What does output do and how do we use it? Well, let’s say we have an input with a type of range. Then we add an output element and correlate it to the input with its for attribute.

<input type="range" name="quantity" id="quantity" min="0" max="100">
<output for="quantity"></output>

See the Pen Input Output #2 by CSS-Tricks (@css-tricks) on CodePen.

It… doesn’t really do anything. By default, output doesn’t have any styles and doesn’t render a box or anything in the browser. Also, nothing happens when we change the value of our input.

We’ll have to tie everything together with JavaScript. No problem! First we need to find our input in the DOM with JavaScript, like so:

const rangeInput = document.querySelector('input');

Now we can append an event listener onto it so that whenever we edit the value (by sliding left or right on our input) we can detect a change:

const rangeInput = document.querySelector('input');

rangeInput.addEventListener('change', function() {
  console.log(this.value);
});

this.value will always refer to the value of the rangeInput because we’re using it inside our event handler and we can then return that value to the console to make sure everything works. After that we can then find our output element in the DOM:

const rangeInput = document.querySelector('input');
const output = document.querySelector('output');

rangeInput.addEventListener('change', function() {
  console.log(this.value);
});

And then we edit our event listener to set the value of that output to change whenever we edit the value of the input:

const rangeInput = document.querySelector('input');
const output = document.querySelector('output');

rangeInput.addEventListener('change', function() {
  output.value = this.value;
});

And voilá! There we have it, well mostly anyway. Once you change the value of the input our output will now reflect that:

See the Pen Input Output #3 by Robin Rendle (@robinrendle) on CodePen.

We should probably improve this a bit by settting a default value to our output so that it’s visible as soon as you load the page. We could do that with the HTML itself and set the value inside the output:

<output for="quantity">50</output>

But I reckon that’s not particularly bulletproof. What happens when we want to change the min or max of our input? We’d always have to change our output, too. Let’s set the state of our output in our script. Here’s a new function called setDefaultState:

function setDefaultState() {
  output.value = rangeInput.value;
}

When the DOM has finished loading and then fire that function:

document.addEventListener('DOMContentLoaded', function(){
  setDefaultState();
});

See the Pen Input Output #4 by Robin Rendle (@robinrendle) on CodePen.

Now we can style everything! But there’s one more thing. The event listener change is great and all but it doesn’t update the text immediately as you swipe left or right. Thankfully there’s a new type of event listener called input with fairly decent browser support that we can use instead. Here’s all our code with that addition in place:

const rangeInput = document.querySelector('input');
const output = document.querySelector('output');

function setDefaultState() {
  output.value = rangeInput.value;
}

rangeInput.addEventListener('input', function() {
  output.value = this.value;
});

document.addEventListener('DOMContentLoaded', function() {
  setDefaultState();
});

See the Pen Input Output #5 by Robin Rendle (@robinrendle) on CodePen.

And there we have it! An input, with an output.