During The Highland Fling (an excellent conference by the way - highly recommend), James Edwards aka Brothercake was talking about the graceful degradation of HTML5 Web Form elements, in particular the input range type.

He points out that degrading to text isn't graceful at all, because with a range, you have predefined options. Much like a select box.

In the wild

In the last week I've worked on two small projects of which both needed a slider aka range element. In one the user gives a rating to an item, 1 - 5. In the second, the user slides from a scale from 10 to 3000.

With <input type=range> the apps looked great. Then I opened them in Firefox 5 and iOS 4.x and there's no range, but a text box. Not useful at all.

Good thing that during James' Q&A session at The Highland Fling I wrote the solution he was describing :)

Jack watching me code

Solution

Instead of the input range, you use a select with a type attribute of range. In that select you offer the options the user can select (in the case of my problem 10-3000, actually I wanted them to chose device widths, so the options were 10, 320, 340, 420, etc for various device widths).

For a rating, here's what you'd have without JavaScript:

<select data-type="range" name="rating">
  <option>1</option>
  <option>2</option>
  <option>3</option>
  <option>4</option>
  <option>5</option>
</select>

After the DOM is ready, my range polyfill kicks in, and upgrades our select elements with data-type=range to an input range type only if the browser supports it. My code tries to replicate all the attributes from the select element, class, id, etc. It will read the first and last options and use those as the min and max, and then read the selected value and use that as the initial value.

The code

You can download it from here: range.js

Here's a live example using the range.js code: https://jsbin.com/atocep/11/edit

I've included the range.js script in my polyfills github repo, so if you find a bug do help yourselves to contributing too.

I've changed the search for the select to look for data-type="range" instead of type="range" - for those validation junkies out there :)