Swizec Teller - a geek with a hatswizec.com

    Datalist, the pure HTML typeahead you didn't know about

    If you ever want to build a searchable typeahead field, <datalist> can do that for you. On all browsers. Across devices. Standards compliant. With no JavaScript. 🀯

    Swizec Teller writing a secret book avatarSwizec Teller writing a secret book@Swizec
    TIL about <datalist>

    This bit of HTML gives you a full featured accessible typeahead search field 🀯
    Tweet media

    I learned about <datalist> from a candidate in an interview. It was great.

    Let's dig in.

    The <datalist> element

    Searchable dropdown components are a combination of an <input> field and a list of options. Typing filters the options so they're easier to find.

    Datalist in action

    You get fuzzy search, keyboard navigation, mouse navigation, and enter to select. Dropdown appears on focus, hides on blur. The selected value is textual.

    I got the list of dog breeds from the dog.ceo API.

    An iPad with a keyboard attached shows this:

    Datalist on an iPad

    And it even works on a phone 🀩

    Datalist on a phone

    You can try it yourself on CodeSandbox

    How you can use <datalist>

    You start with an input field:

    <input name="dogBreed" list="breeds" />

    The list attribute defines which datalist you want to use. This is a globally unique identifier on the page.

    Add a datalist component with your options:

    <datalist id="breeds">
    <option value="affenpinscher"></option>
    <option value="african"></option>
    <option value="airedale"></option>
    <option value="akita"></option>
    <option value="appenzeller"></option>
    <option value="australian shepherd"></option>
    <option value="basenji"></option>
    <!-- ... -->

    And that's it. The id identifies your list and the browser handles the rest. You now have a standards compliant full featured typeahead field that works in any browser.

    If you want to package this as a reusable component, you'll have to generate the id and list attributes on render. Needs to be unique on the page.

    <datalist> as a React component

    A reusable React datalist needs to

    1. work as multiple instances on the page
    2. render options from a list
    3. return values with a callback

    No. 3 is optional. You can do that using form machinery like react-hook-form.

    You end up with a component like this:

    const Datalist = ({ name, options, onChange }) => {
    // this is a bad id for example purposes
    // in React 18 you'd use useId()
    const id = new Date().getTime()
    return (
    <input name={name} list={id} onChange={onChange} />
    <datalist id={id}>
    {options.map((o) => (
    <option value={o} />

    We use a poor man's unique identifier – the current time in milliseconds. It's okay, but you'll want to use useId when React 18 comes out and find a more robust solution until then.

    We call onChange for every input change. This may be annoying for consumers of our component.

    A nice option would be to check the value against your list of options on every change and call an onSelected callback when there's a match. That way you can catch when the user makes an explicit selection. Probably.

    <datalist> as a dynamic React component

    If you have too many options to list or need richer search behavior, you could expand this component with a dynamic search. Like this:

    const DynamicDatalist = ({ name, api, onChange }) => {
    // this is a bad id for example purposes
    // in React 18 you'd use useId()
    const id = new Date().getTime()
    const [options, setOptions] = useState([])
    async function runSearch(event) {
    const value = event.currentTarget.value
    // you'll want to debounce this
    const data = await fetchFrom(`${api}?search=${value}`)
    return (
    <input name={name} list={id} onChange={runSearch} />
    <datalist id={id}>
    {options.map((o) => (
    <option value={o} />

    Assume this is pseudocode.

    You watch for changes, run API requests, and use those to populate the options list dynamically. Be careful about blindly running requests on every keystroke.

    Eric Burel avatarEric Burel@ericbureltech
    @Swizec I gave it a shot here: . It seems to work as expected indeed! Thanks for the tip, I was looking for a vanilla HTML typeahead just yesterday.

    What <datalist> can't do

    You can't style a datalist. I think this is strictly better.

    Swizec Teller writing a secret book avatarSwizec Teller writing a secret book@Swizec
    @thepanta82 In my experience those custom things always have a worse UX than the default browser component. I wish designers stopped insisting on customizing this stuff πŸ˜‡

    You also can't use this to build the multiselect combobox thingy that's popular these days. The inputs that show your choices as pills next to your typing.

    A combobox multiselect, not possible with datalist
    A combobox multiselect, not possible with datalist

    You can't use rich option values like objects. It's a text. Unless you build it yourself as part of a <Datalist> component.

    And you'll have to make your own validation that the final value is on the list. A normal <select> might be a better option there.

    Ashley Ryan πŸ‘©πŸΌβ€πŸ’» avatarAshley Ryan πŸ‘©πŸΌβ€πŸ’»@ashleyepryan
    @ericbureltech @Swizec The data list element is a text box with a list of suggestions. If you don’t support open ended text, it’s not useful.

    It’s not a combobox/searchable select, which is something that tripped me up at first.

    Next time you build a typehead, consider the <datalist>. It might serve you better than a 81kb React library.


    PS: <datalist> works with Vue, Svelte, etc. I used React because that's more comfortable for me

    Did you enjoy this article?

    Published on December 14th, 2021 in Frontend, HTML,

    Learned something new?
    Read more Software Engineering Lessons from Production

    I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.

    Subscribe below πŸ‘‡

    Software Engineering Lessons from Production

    Join Swizec's Newsletter and get insightful emails πŸ’Œ on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

    "Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. πŸ‘Œ"

    ~ Ashish Kumar

    Join 15,883+ engineers learning lessons from my "raw and honest from the heart" emails.

    4.5 stars average rating

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help πŸ‘‰ swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers πŸ‘‰ ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Want to brush up on modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❀️

    Created by Swizec with ❀️