Relevant Dropdowns: Polyfill for Datalist

Chris Coyier //

The list attribute / datalist element of HTML5 forms is pretty cool. As you type in a text input, it shows you a dropdown menu of choices you can pick from. Or you can type in whatever you want. The list attribute alone doesn't lock you into any specific value. In that way, it's a bit like a group of radio buttons with an "other" type-in option.

It's like this:

<input type="text" id="search" list="states" placeholder="Find U.S. State">
	
<datalist id="states">
  <option value="Alabama">
  <option value="Alaska">
  <!-- All the other states -->
</datalist>

and turns out like this:

Supported browser (Firefox 8) showing relevant choices for what has already been typed into the text input.

Unfortunately, browser support for datalist (at the time of this writing) is limited to Firefox 4+, Opera 10.6+, and the not-yet-released IE 10. It's reasonable that you'd want WebKit support (and older browser support) for this useful feature. So I made this polyfill. It relies on Modernizr for detection and jQuery to make it work.

Unsupported browser (Chrome 16) with just about the same functionality.

I got it working on iOS 5, IE 6+, Chrome (probably any), and Safari (probably any). Older IE's don't have the box shadow but you could style it however you want with CSS.

Like any polyfill, you start with the correct most-modern markup, and it "just works" in older browsers. This one simulates the dropdown and the selecting of an option from the dropdown. It has keyboard support (up and down arrows and selecting with return) and positions itself correctly even when the window resizes.

Safari required an extra hack since it claims support of the list attribute and datalist element but it doesn't actually work. Thus the Modernizr detection is incorrect. So because Safari has these really high browser version numbers that nobody else has, we can just test for that with jQuery.

if (!Modernizr.input.list || (parseInt($.browser.version) > 400))

Update on the above from Lee Reamsnyder to prevent newer Chromes from false positive:

if (!Modernizr.input.list || (parseInt($.browser.version) > 400 && !window.chrome))

Here it is:

View Demo

It's not perfect. It should probably be a plugin and work on multiple inputs. It should look better in IE. The code could probably be optimized. It's on GitHub if you want to download it or fork it or whatever.

Update (October 2012)

Fixed GitHub Link
Updated to jQuery 1.8
Updated custom :contains method for jQuery 1.8