Search input
Category: Forms · Tags: search, clear, input, role-search, filter
How to use it
Use for a site or section search box, or to filter a long list on the same page. Keep the visible label (or at least the Search button) rather than relying on placeholder text, and say what is being searched. For picking one value from a known list use a select or combobox instead. Change the aria-label, ids and the submit handler -- set the form's action and remove preventDefault to search a real results page.
Accessibility
The form has role="search" and an aria-label, so it is listed as a search landmark. The native type="search" input has a <label for>; the clear button is a native <button> named "Clear search" that is hidden until there is text, and pressing it empties the field and returns focus to it (Escape in the field also clears it). Submitting writes the result into a role="status" line. Buttons and the field show a 2px focus outline. Text is #0f172a on #ffffff (17.85:1), the clear button #0f172a on #ffffff and on the #e2e8f0 hover (14.48:1), and the search button #ffffff on #1d4ed8 (6.70:1) and the #1e40af hover (8.72:1).
Source (copy-ready)
<form class="dcl-search" role="search" aria-label="Help articles">
<label class="dcl-search__label" for="dcl-search-query">Search help articles</label>
<div class="dcl-search__row">
<div class="dcl-search__field">
<input class="dcl-search__input" id="dcl-search-query" name="q" type="search" autocomplete="off">
<button type="button" class="dcl-search__clear" aria-label="Clear search" hidden>
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false"><path d="M4 4l8 8M12 4l-8 8" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</button>
</div>
<button type="submit" class="dcl-search__submit">Search</button>
</div>
<p class="dcl-search__status" role="status"></p>
</form>
<style>
.dcl-search { max-width: 28rem; font: inherit; color: #0f172a; background-color: #ffffff; }
.dcl-search__label { display: block; margin-bottom: 0.35rem; font-weight: 600; color: #0f172a; background-color: #ffffff; }
.dcl-search__row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.dcl-search__field { position: relative; flex: 1 1 12rem; min-width: 0; }
.dcl-search__input { width: 100%; box-sizing: border-box; min-height: 2.75rem; padding: 0.5rem 2.75rem 0.5rem 0.75rem; border: 1px solid #64748b; border-radius: 0.5rem; font: inherit; color: #0f172a; background-color: #ffffff; }
.dcl-search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.dcl-search__input:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 1px; }
.dcl-search__clear { position: absolute; top: 50%; right: 0.25rem; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem; padding: 0; border: none; border-radius: 0.375rem; cursor: pointer; color: #0f172a; background-color: #ffffff; }
.dcl-search__clear[hidden] { display: none; }
.dcl-search__clear:hover { color: #0f172a; background-color: #e2e8f0; }
.dcl-search__clear:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 1px; }
.dcl-search__submit { min-height: 2.75rem; padding: 0 1.1rem; border: none; border-radius: 0.5rem; cursor: pointer; font: inherit; font-weight: 600; color: #ffffff; background-color: #1d4ed8; }
.dcl-search__submit:hover { color: #ffffff; background-color: #1e40af; }
.dcl-search__submit:focus-visible { outline: 2px solid #0f172a; outline-offset: 2px; }
.dcl-search__status { min-height: 1.5em; margin: 0.5rem 0 0; overflow-wrap: anywhere; color: #0f172a; background-color: #ffffff; }
</style>
<script>
(function () {
document.querySelectorAll(".dcl-search").forEach(function (root) {
if (root.dataset.dclBound) { return; }
root.dataset.dclBound = "true";
var input = root.querySelector(".dcl-search__input");
var clear = root.querySelector(".dcl-search__clear");
var status = root.querySelector(".dcl-search__status");
if (!input) { return; }
function sync() { if (clear) { clear.hidden = input.value === ""; } }
input.addEventListener("keydown", function (event) {
if (event.key === "Escape" && input.value !== "") { event.preventDefault(); input.value = ""; sync(); if (status) { status.textContent = ""; } }
});
input.addEventListener("input", sync);
if (clear) {
clear.addEventListener("click", function () {
input.value = "";
sync();
if (status) { status.textContent = ""; }
input.focus();
});
}
root.addEventListener("submit", function (event) {
event.preventDefault();
var query = input.value.trim();
if (status) { status.textContent = query ? "Showing results for “" + query + "”." : "Type something to search."; }
});
sync();
});
})();
</script>
Was this useful? Send feedback.