How to build custom search bar with HTML and CSS without JavaScript #1
Search bar is one of the most common UI components in the web. Every search engine has one. Trough search bars we interact with the web. Let’s build one for our website.
Layout
Base
To perform a search inside our website we need to send a GET
request with some parameter (usually its q
as in “query”). The easiest way to do this with plain HTML is by using <form>
element with method="GET”
and action
attributes alongside with input
element named q
and a button
with submit
type.
<form action="/search"
method="GET">
<fieldset>
<input type="search"
name="q"
placeholder="Search the website"
required />
<button type="submit">Search</button>
</fieldset>
</form>
Now when user clicks submit button, browser will send a GET
request to /search
with query q={value}
.
Reset functionality and accessibility
To give user ability to clear form inputs (in our case just the search input value) we should add input type="reset"
. Now by clicking on input type="reset"
the value in the input type="search"
will become null. Since all input
elements must have accessible label
element, let’s wrap our input type="search"
and input type="reset"
in label
.
<form action="/search"
method="GET">
<fieldset>
<label>
<input type="search"
name="q"
placeholder="Search the website"
required />
<input type="reset" />
</label>
<button type="submit">Search</button>
</fieldset>
</form>
Style
Images
For our search bar to have an outstanding view we will add magnifying glass icon before input type="search"
and X
icon instead of input type="reset"
button.
<img src="data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaGVhZGVyLXNlYXJjaF9fZm9ybV9fZ2xhc3MiCiAgICAgd2lkdGg9IjIwIiBoZWlnaHQ9IjIxIgogICAgIHZpZXdCb3g9IjAgMCAyMCAyMSIKICAgICBmaWxsPSJub25lIgogICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuMTYxNTMgOS4yNjQ3MUMyLjE2MTUzIDUuNjgyOTggNS4wNjUxIDIuNzc5NDEgOC42NDY4MyAyLjc3OTQxQzEyLjIyODYgMi43Nzk0MSAxNS4xMzIxIDUuNjgyOTggMTUuMTMyMSA5LjI2NDcxQzE1LjEzMjEgMTEuMDUyNyAxNC40MDk4IDEyLjY3MDMgMTMuMjM4NyAxMy44NDQ0QzEyLjA2MzYgMTUuMDIyNiAxMC40NDEgMTUuNzUgOC42NDY4MyAxNS43NUM1LjA2NTEgMTUuNzUgMi4xNjE1MyAxMi44NDY0IDIuMTYxNTMgOS4yNjQ3MVpNOC42NDY4MyAwLjkyNjQ3MkM0LjA0MTc1IDAuOTI2NDcyIDAuMzA4NTk0IDQuNjU5NjMgMC4zMDg1OTQgOS4yNjQ3MUMwLjMwODU5NCAxMy44Njk4IDQuMDQxNzUgMTcuNjAyOSA4LjY0NjgzIDE3LjYwMjlDMTAuNjE1MiAxNy42MDI5IDEyLjQyNTQgMTYuOTIgMTMuODUxNCAxNS43Nzk1TDE3Ljg3NDEgMTkuODAyMkMxOC4yMzU5IDIwLjE2NCAxOC44MjI1IDIwLjE2NCAxOS4xODQzIDE5LjgwMjJDMTkuNTQ2MSAxOS40NDA0IDE5LjU0NjEgMTguODUzOCAxOS4xODQzIDE4LjQ5MTlMMTUuMTYxNiAxNC40NjkzQzE2LjMwMjEgMTMuMDQzMiAxNi45ODUxIDExLjIzMzEgMTYuOTg1MSA5LjI2NDcxQzE2Ljk4NTEgNC42NTk2MyAxMy4yNTE5IDAuOTI2NDcyIDguNjQ2ODMgMC45MjY0NzJaIiBmaWxsPSJyZ2IoMTQ3LCAxNTMsIDE3MikiLz4KPC9zdmc+Cg==" width="20" height="21" />
<input type="reset" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiCiAgICAgdmlld0JveD0iMCAwIDEyIDEyIgogICAgIGZpbGw9Im5vbmUiCiAgICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xMS43MDcxIDEuNzA3MTFDMTIuMDk3NiAxLjMxNjU4IDEyLjA5NzYgMC42ODM0MTcgMTEuNzA3MSAwLjI5Mjg5M0MxMS4zMTY2IC0wLjA5NzYzMTEgMTAuNjgzNCAtMC4wOTc2MzExIDEwLjI5MjkgMC4yOTI4OTNMMTEuNzA3MSAxLjcwNzExWk0wLjI5Mjg5MyAxMC4yOTI5Qy0wLjA5NzYzMTEgMTAuNjgzNCAtMC4wOTc2MzExIDExLjMxNjYgMC4yOTI4OTMgMTEuNzA3MUMwLjY4MzQxNyAxMi4wOTc2IDEuMzE2NTggMTIuMDk3NiAxLjcwNzExIDExLjcwNzFMMC4yOTI4OTMgMTAuMjkyOVpNMTAuMjkyOSAxMS43MDcxQzEwLjY4MzQgMTIuMDk3NiAxMS4zMTY2IDEyLjA5NzYgMTEuNzA3MSAxMS43MDcxQzEyLjA5NzYgMTEuMzE2NiAxMi4wOTc2IDEwLjY4MzQgMTEuNzA3MSAxMC4yOTI5TDEwLjI5MjkgMTEuNzA3MVpNMS43MDcxMSAwLjI5Mjg5M0MxLjMxNjU4IC0wLjA5NzYzMTEgMC42ODM0MTcgLTAuMDk3NjMxMSAwLjI5Mjg5MyAwLjI5Mjg5M0MtMC4wOTc2MzExIDAuNjgzNDE3IC0wLjA5NzYzMTEgMS4zMTY1OCAwLjI5Mjg5MyAxLjcwNzExTDEuNzA3MTEgMC4yOTI4OTNaTTEwLjI5MjkgMC4yOTI4OTNMMC4yOTI4OTMgMTAuMjkyOUwxLjcwNzExIDExLjcwNzFMMTEuNzA3MSAxLjcwNzExTDEwLjI5MjkgMC4yOTI4OTNaTTExLjcwNzEgMTAuMjkyOUwxLjcwNzExIDAuMjkyODkzTDAuMjkyODkzIDEuNzA3MTFMMTAuMjkyOSAxMS43MDcxTDExLjcwNzEgMTAuMjkyOVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=')"/>
CSS rules
Now let’s do some CSS magic. First, add classes to elements.
<form class="form">
<fieldset class="form__fieldset">
<label class="form__label"
for="searchbar">
<img class="form__glass"/>
<input type="search"
id="searchbar"
name="q"
class="form__input"/>
<input type="reset"
class="form__reset"/>
</label>
<button class="form__submit"
type="submit">Search</button>
</fieldset>
</form>
And finally, add some CSS for better visibility and accessibility.
input, button {
background: none;
outline: none;
border: none;
color: transparent;
background-repeat: no-repeat;
}
.form {
width: 100%;
&:invalid {
& .form__reset {
opacity: 0;
pointer-events: none;
}
& .form__button {
pointer-events: none;
pointer: default;
}
}
&:valid {
& .form__reset {
opacity: 1;
pointer-events: all;
}
}
&__label {
display: flex;
align-items: center;
padding: 10px 20px;
background-color: black;
border: 1px solid transparent;
border-radius: 5px;
transition: border 0.066s linear;
&:hover {
border: 1px solid cyan;
}
&:focus-within {
border: 1px solid blue;
}
}
&__fieldset {
display: flex;
align-items: center;
justify-items: stretch;
width: 100%;
}
&__input {
display: inline-block;
vertical-align: middle;
min-width: 200px;
width: 100%;
background-color: transparent;
color: white;
&::placeholder {
color: lightgray;
}
}
&__glass {
justify-self: start;
vertical-align: middle;
margin-right: 10px;
}
&__reset {
justify-self: end;
vertical-align: middle;
cursor: pointer;
padding: 5px;
margin-left: 10px;
width: 12px;
height: 12px;
background-position: center;
background-size: 12px 12px;
background-repeat: no-repeat;
border: 1px solid transparent;
transform-origin: center;
transform: rotate(0);
transition:
border 0.066s linear,
transform 0.066s linear,
opacity 0.15s linear;
@media (prefers-reduced-motion: true) {
transition: none;
}
&:hover {
transform: rotate(90deg);
}
&:focus {
border: 1px solid blue;
}
}
&__button {
margin-left: 5px;
background-color: black;
color: white;
align-self: stretch;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
}
}
Result
As a result, we now have accessible searchbar with reset functionality and some fancy icons working without a single line of JavaScript. Final result available on Codepen.