datalist
Provides autocomplete suggestions for input elements. The datalist creates a native dropdown of options that users can select from while still allowing free-form text entry.
When to Use
- Providing suggestions while allowing custom values (e.g., country input)
- Autocomplete functionality without JavaScript
- Search inputs with common suggestions
- When users might enter values not in the predefined list
Use select instead when users must choose from a fixed set of options.
Need more control? The combo-box web component offers keyboard navigation, filtering, custom rendering, and full styling control — a good upgrade path when native datalist falls short.
Basic Usage
Connect an input to a datalist using the list attribute on the input and an id on the datalist.
Code
<label for="browser">Browser</label><input type="text" id="browser" list="browsers" placeholder="Start typing..." /><datalist id="browsers"> <option value="Chrome"></option> <option value="Firefox"></option> <option value="Safari"></option> <option value="Edge"></option> <option value="Opera"></option></datalist>
Input Variants
Inputs with a list attribute display a dropdown arrow by default. Use .no-arrow to hide it, or .search for a search icon on the left.
Code
<!-- No dropdown arrow --><input type="text" list="options" class="no-arrow" /> <!-- Search style with icon --><input type="search" list="options" class="search" />
Options with Labels
Options can include a label displayed alongside the value. The value is what gets submitted, while the label provides additional context.
Code
<datalist id="airports"> <option value="JFK" label="John F. Kennedy International"></option> <option value="LAX" label="Los Angeles International"></option> <option value="ORD" label="Chicago O'Hare"></option></datalist>
With Different Input Types
Datalist works with various input types beyond text: email, URL, and range.
Using with form-field
For enhanced accessibility and validation, wrap datalist inputs in the form-field custom element.
Code
<form-field> <label for="country">Country</label> <input type="text" id="country" name="country" list="countries" required autocomplete="country-name" aria-describedby="country-msg" /> <datalist id="countries"> <option value="United States"></option> <option value="Canada"></option> <!-- more options --> </datalist> <output id="country-msg" for="country" aria-live="polite"> Start typing to see suggestions </output></form-field>
Recipes
These patterns extend the basic datalist with small amounts of JavaScript. The scripts live in the demo page, not in VB core — copy and adapt as needed.
Detect List Match vs Custom Entry
Check whether the user picked a value from the suggestion list or typed their own. Useful for conditional validation or analytics.
const input = document.getElementById('country-input');const options = [...document.querySelectorAll('#country-list option')].map(o => o.value); input.addEventListener('input', () => { const v = input.value.trim(); const isMatch = options.includes(v); // isMatch === true → user picked from the list // isMatch === false → user typed a custom value});
Dynamic Server-Driven Suggestions
Populate datalist options from an API endpoint with debounced input. The demo simulates a 150ms fetch; replace with a real endpoint in production.
<input type="search" id="city-input" list="city-suggestions" autocomplete="off" /><datalist id="city-suggestions"></datalist> <script> const input = document.getElementById('city-input'); const datalist = document.getElementById('city-suggestions'); let timer; input.addEventListener('input', () => { clearTimeout(timer); if (input.value.length < 2) { datalist.innerHTML = ''; return; } timer = setTimeout(async () => { const res = await fetch(`/api/cities?q=${input.value}`); const cities = await res.json(); datalist.innerHTML = cities .map(c => `<option value="${c}">`) .join(''); }, 300); });</script>
Range with Visible Tick Labels
Datalist on a range input adds tick marks at each <option> value. Pair with visible labels and a live <output> for clear feedback.
<input type="range" min="0" max="5000" step="500" value="2500" list="budget-ticks" /><datalist id="budget-ticks"> <option value="0"></option> <option value="500"></option> <option value="1000"></option> <!-- ... --> <option value="5000"></option></datalist><output id="budget-value" for="budget-range">$2,500</output> <script> const range = document.querySelector('input[type="range"]'); const output = document.getElementById('budget-value'); const fmt = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }); range.addEventListener('input', () => { output.textContent = fmt.format(range.value); });</script>
Color Palette with Swatch Companion
A <input type="color" list="..."> shows palette swatches inside the native color picker on Chromium. The JS-rendered swatch buttons work cross-browser as a progressive enhancement companion.
<input type="color" id="color-picker" list="brand-palette" value="#c84b2f" /><datalist id="brand-palette"> <option value="#c84b2f"></option> <option value="#2d6a4f"></option> <option value="#4a7fbd"></option></datalist> <script> // Cross-browser swatch companion const picker = document.getElementById('color-picker'); const colors = [...document.querySelectorAll('#brand-palette option')] .map(o => o.value); colors.forEach(hex => { const btn = document.createElement('button'); btn.type = 'button'; btn.style.background = hex; btn.addEventListener('click', () => { picker.value = hex; }); container.appendChild(btn); });</script>
Datalist vs combo-box
Choose based on the level of control you need:
| Feature | datalist | combo-box |
|---|---|---|
| JavaScript required | No | Yes |
| Custom styling | Browser-controlled | Full control |
| Keyboard navigation | Browser default | ARIA combobox pattern |
| Custom filtering | Browser default | Configurable |
| Rich option content | Text only | HTML templates |
| Free-text entry | Always allowed | Configurable |
Accessibility Notes
- Always include a label: The input must have an associated label
- Screen reader support: Native datalist is well-supported by assistive technologies
- Keyboard navigation: Users can navigate options with arrow keys
- Allow custom values: Unlike select, datalist allows users to enter values not in the list
- Provide fallback: The input works without the datalist in older browsers
CSS Reference
/* Input with datalist indicator */input[list] { background-image: url("data:image/svg+xml,..."); /* dropdown arrow */ background-repeat: no-repeat; background-position: right var(--size-s) center; padding-inline-end: var(--size-xl);} /* Hide the dropdown arrow */input[list].no-arrow { background-image: none; padding-inline-end: var(--size-s);} /* Search-style datalist input */input[list].search { background-image: url("data:image/svg+xml,..."); /* search icon */ background-position: left var(--size-s) center; padding-inline-start: var(--size-xl); padding-inline-end: var(--size-s);} /* The datalist element itself is hidden */datalist { display: none;}
Browser Support Notes
- Datalist is supported in all modern browsers
- Visual appearance varies between browsers (cannot be fully styled)
- The dropdown behavior is controlled by the browser
- On mobile devices, the suggestions may appear in a different format
type="color"with datalist shows palette swatches in Chromium browsers; Firefox and Safari fall back to the standard color picker