One of the many form enhancements provided by HTML5 is the datalist
element. It allows you to turn a regular input
field into a combo-box.
Using the list
attribute on an input
, you can connect it to a datalist
with the corresponding ID. The datalist
itself contains a series of option
elements.
<input list="suggestions">
<datalist id="suggestions">
<option value="foo"></option>
<option value="bar"></option>
<option value="baz"></option>
</datalist>
I can imagine a number of use cases for this:
- “Share this” forms, like the one on Last.fm, that allow you to either select from your contacts on the site, or enter email addresses, separated by commas. Using
input type="email"
with a multiple
attribute, in combination with a datalist
would work nicely.
- Entering the details for an event, where you can either select from a list of venues or, if the venue is not listed, create a new one.
- Just about any form that has a selection of choices, of which the last choice is “other”, followed by “If other, please specify…”
You can take something like this:
<label for="source">How did you hear about us?</label>
<select name="source">
<option>please choose...</option>
<option value="television">Television</option>
<option value="radio">Radio</option>
<option value="newspaper">Newspaper</option>
<option>Other</option>
</select>
If other, please specify:
<input id="source" name="source">
And replace it with this:
<label for="source">How did you hear about us?</label>
<datalist id="sources">
<option value="television"></option>
<option value="radio"></option>
<option value="newspaper"></option>
</datalist>
<input id="source" name="source" list="sources">
The datalist
element has been designed according to one of the design principles driving HTML5—Degrade Gracefully:
On the World Wide Web, authors are often reluctant to use new language features that cause problems in older user agents, or that do not provide some sort of graceful fallback. HTML 5 document conformance requirements should be designed so that Web content can degrade gracefully in older or less capable user agents, even when making use of new elements, attributes, APIs and content models.
Because the datalist
element contains a series of option
elements with value
attributes, it is effectively invisible to user-agents that don’t support the datalist
element. That means you can use the datalist
element without worrying it “breaking” in older browsers.
If you wanted, you could include a message for non-supporting browsers:
<datalist id="sources">
Your browser doesn't support datalist!
<option value="television"></option>
<option value="radio"></option>
<option value="newspaper"></option>
</datalist>
That message—“Your browser doesn’t support datalist!”—will be visible in older browsers, but browsers that support datalist
know not to show anything that’s not an option
. But displaying a message like this for older browsers is fairly pointless; I certainly wouldn’t consider it graceful degradation.
In my opinion, one of the best aspects of the design of the datalist
element is that you can continue to do things the old-fashioned way—using a select
and an input
—and at the same time start using datalist
. There’s no violation of the DRY principle either; you can use the same option
elements for the select
and the datalist
:
<label for="source">How did you hear about us?</label>
<datalist id="sources">
<select name="source">
<option>please choose...</option>
<option value="television">Television</option>
<option value="radio">Radio</option>
<option value="newspaper">Newspaper</option>
<option>Other</option>
</select>
If other, please specify:
</datalist>
<input id="source" name="source" list="sources">
Browsers that support datalist
will display the label
“How did you hear about us?” followed by a combo-box text field that allows the user to select an option, or enter some free text.
Browsers that don’t support datalist
will display the the label
“How did you hear about us?” followed by a drop-down list of of options (the last of which is “other”), followed by the text “If other, please specifiy”, followed by a text field.
Take a look at this example in Opera to see datalist
in operation. Take a look at it in any other browser to see the fallback. The source is on Github if you’d like to play around with it.
WebKit’s mistake
If you try that example in any browser, you’ll get something that works; either through datalist
support or through the select
fallback …unless the browser is using WebKit.
It took me a while to figure out why this would be the case. I didn’t think that Safari or Chrome supported datalist
and a little digging around with object detection in JavaScript confirmed this. So why don’t those browsers follow the standard behaviour and simply ignore the element they don’t understand and render what’s inside it instead.
Here’s the problem: line 539 of WebKit’s default CSS:
datalist {
display: none;
}
This is pretty much the worst possible behaviour for a browser to implement. An element should either be recognised—like p
, h1
or img
—and parsed accordingly, or an element is unrecognised—like foo
or bar
—and ignored. WebKit does not support the datalist
element (even in the current nightly build), so the element should be ignored.
Fortunately the problem is easily rectified by adding something like this to your own stylesheet:
datalist {
display: inline-block;
}
I’ve submitted a bug report on the WebKit Bugzilla.
Update: That Webkit bug has now been fixed so the extra CSS is no longer necessary.