Interactive demos of hcg-searchable-select, a lightweight zero-dependency
searchable dropdown for native <select> elements. Try filtering,
optgroups, clearable selection, disabled state, form validation, dynamic options,
and the JavaScript API.
Full documentation
Add data-hcg-select and type in the search box to filter options.
<select data-hcg-select data-placeholder="Select a country">
<option value="">- Select a country -</option>
<option value="us">United States</option>
</select>
Native <optgroup> elements render as non-selectable headers.
<select data-hcg-select>
<option value="">- Pick food -</option>
<optgroup label="Fruits">
<option value="apple">Apple</option>
</optgroup>
</select>
Add data-clearable to show a clear button when a value is chosen.
<select data-hcg-select data-clearable data-placeholder="Choose a city">
<option value="">- Choose a city -</option>
<option value="par">Paris</option>
</select>
A select with a default selected option shows that label on load.
<select data-hcg-select>
<option value="free">Free</option>
<option value="pro" selected>Pro</option>
</select>
Disabled selects cannot open; individual options can be marked disabled.
<select data-hcg-select disabled>...</select>
<select data-hcg-select>
<option value="legacy" disabled>Legacy (unavailable)</option>
</select>
Call hcgSelect() with custom placeholders and an onChange callback.
hcgSelect("#demo-manual", {
placeholder: "Choose a language",
searchPlaceholder: "Type to filter…",
onChange: function (value) {
console.log("Selected:", value);
}
});
Filter a large list; matching text is highlighted in the dropdown.
<!-- Same markup as a normal select; filtering is built in -->
<select data-hcg-select data-placeholder="Search time zones">
<option value="ist">Asia/Kolkata (IST)</option>
</select>
Control the widget with open(), close(), clear(), and setDisabled().
const api = hcgSelect("#demo-api", { clearable: true });
api.open();
api.close();
api.clear();
api.setDisabled(true);
Add or remove options at runtime; the list rebuilds automatically. Call refresh() after bulk changes if needed.
const opt = document.createElement("option");
opt.value = "games";
opt.textContent = "Games";
select.appendChild(opt);
// list rebuilds via MutationObserver; or call api.refresh()
The native required attribute and browser validation still work; the widget mirrors aria-required and aria-invalid.
<form>
<select name="country" data-hcg-select required>
<option value="">- Select a country -</option>
<option value="us">United States</option>
</select>
<button type="submit">Submit</button>
</form>