Show Search Button when Search Field is Non-Empty

Avatar of Chris Coyier
Chris Coyier on

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

I think the :placeholder-shown selector is tremendously cool. It allows you to select the placeholder of an input (<input placeholder="...">) when that placeholder is present. Meaning, the input does not yet have any value. You might think input[value] could do that, or help match on the actual value, but it can’t.

This makes :placeholder-shown one of the few CSS properties that we have that can react to user-initiated state joining the likes of :hover-and-friends, :checked (checkbox hack!), and the also-awesome :focus-within.

One way we can use it is to check whether the user entered any text into a search field. If yes, then reveal the search button visually (never hide it for assistive tech). If no, then leave it hidden. It’s just a fun little “space-saving” technique not terrible unlike float labels.

So, perhaps we start with a semantic search form:

<form action="#" method="GET" class="search-form">
  <!-- Placeholders aren't labels! So let's have a real label -->
  <label for="search" class="screen-reader-text">Search</label>
  <input id="search" type="search" class="search-input" placeholder="Enter search terms...">
  <button class="search-button">Search</button>

We hide the search label visually with one of those special screen-reader-only classes because it will always be hidden visually. But we’ll hide the button by pushing it outside the form with hidden overflow.

.search-form {
  /* we'll re-use this number, so DRYing up */
  --searchButtonWidth: 75px;

  overflow: hidden;
  position: relative;

.search-input {
  /* take full width of form */
  width: 100%;

.search-button {
  position: absolute; 
  /* push outside the form, hiding it */
  left: 100%;
  width: var(--searchButtonWidth);

Then the trick is to pull the search button back in when the placeholder goes away (user has entered a value):

/* ... */

.search-input:not(:placeholder-shown) ~ .search-button {
  /* pull back the negative value of the width */
  transform: translateX(calc(-1 * var(--searchButtonWidth)));
.search-button {
  position: absolute; 
  left: 100%;
  width: var(--searchButtonWidth);
  /* animate it */
  transition: 0.2s;

Which ends up like this:

See the Pen
:placeholder-shown revealing button
by Chris Coyier (@chriscoyier)
on CodePen.

I saw this idea in a Pen by Liam Johnston. Cool idea, Liam!

I know that using the placeholder attribute at all is questionable, so your mileage may vary. I’ll admit that I’m mostly intrigued by the state-handling aspects of it directly in CSS and how it can be used — like the infamous checkbox hack.

Support is good. One of those where when Edge is firmly Chromium, it’s in the clear.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.



Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari