For those moments when you want to build a search, with autocomplete, but you don’t want to use JavaScript for the suggestions.
The Problem
Let’s say you’re tasked with building this new Search 🔎 component, but to show your CSS prowess, or just to be more efficient, you want to manage the show/hide state of the suggestions just with CSS. After all, it doesn’t make sense write a whole focus-lost
directive for this.
Good to know
Not much, this post relies only on HTML and CSS knowledge 📚.
The Solution
We’ll split this into a couple of steps:
- Build the HTML of the component
- Add some basic CSS styling
- The magic touch 🧙♂️
Let’s go!
Part 1 - Build the HTML of the component
We need our building blocks. What’s a search? It’s an input
. So, we start with this:
Nothing fancy here. A simple input
, with a type and some placeholder
text.
Next to this, we’ll need a place to put all our search results. The result could be something like this:
And that’s it. One small note, we’ve put everything inside a div
, to have it wrapped nicely.
Part 2 - Add some CSS styling
Now, let’s make this subjectively ugly thing, a bit prettier. We’ll start with the input
.
A couple of things to notice here:
- We’ve added “nice” colors to the text, border and placeholder.
- We’ve added some spacing.
- We’ve added some rounded borders, to make our input more pleasant to look at.
- We’ve increased the
outline-offset
for when theinput
isfocus
, to make sure it’s clear for people using assistive technology.
Now, let’s add some styling to our list of results
To note, here, besides the color and the spacing:
- We’ve set the
list-style
tonone
, to get rid of the ⚫️ in front of each item. - We’ve set a maximum height to 300px. In case our search has to many results, we’re limiting the amount of space they take.
- This is combined with an
overflow-y
ofauto
to take care of adding a scroll bar if there are too many results.
Finally, some basic styling for each result item:
Here we’re making sure each value does not wrap, to take more than one row. It will simply vanish on the right (or left, depending on your locale). This is just a choice, feel free to do something magical ✨ here.
With the styling done, we need to properly place the results under the search input
. This is done easily with absolute positioning.
Here we’re making sure the container has relative positioning
, and within it, we’re placing our list with position: absolute;
. You’ll notice that there are no adjustments to the place it sits in. There’s not top
, right
, bottom
or left
property. This is because we’ve already set the width
to be 100%, and the height
will be as much as needed, up to a maximum of 300px.
Important to note is the z-index
as well. We want to make sure our results will sit on top of our content.
Easy peasy 🫛 right? With this, we have a “fully-styled” search component 🔎.
Now, for the last bit.
Part 3 - The magic touch 🧙♀️
I feel like I’ve built this up too much. It’s not THAT magical.
So, we want to type something in our input
, see some results, and maybe click outside our input
or outside our list. When this happens, the results list should be hidden. Right?
:focus-within
to the rescue 🚑!
Looks like a weird selector, but let me walk you through it.
- First, we’re selecting our
div
wrapper. - Then, we’re putting a condition on it not having focus within. As in, no child of this div wrapper is focused.
- Then, when this condition is fulfilled, we select the
ul
inside thediv
. - Last but not least, we hide this
ul
element.
In other words, we could rephrase it like this:
Select the
list
that lives inside adiv
element which has no focused child
Hope this makes more sense 🧐
See, it wasn’t that magical 🪄. Just a super nice CSS property :focus-within
Here’s how the final result looks like:
- Batman
- Joker
- Harley Quinn
- Nightwing
- Bane
Also, here's a link to a working StackBlitz.
Congrats 🎉
You made it yet through another article. Thanks for spending the time reading this, and hope it provided some sort of value, since time is a limited resource. Use it wisely. 🙏
Want more?
If you want to know more about this, or something doesn't make any sense, please let me know.
Also, if you have questions, you know where to find me… On the internet!
Be kind to each other! 🧡
Over and out
It's been a while ⏰, I know, but here's a new short post on how to hide an element on focus lost without using JavaScript 🚀: https://catalincodes.com/posts/css-tidbits-how-to-hide-element-on-focus-lost #HTML #CSS #UI