DEV Community

Cover image for Possibly the Most Useful CSS Trick
Gabriel Romualdo
Gabriel Romualdo

Posted on • Updated on • Originally published at

Possibly the Most Useful CSS Trick

This post is originally from my personal website, where you can read about me, check out my projects, and more.

Imagine you are building a simple search form, where a user types their search into an input box, and then clicks the search button to search.

Here's some sample HTML for the search form:

<input placeholder="Search...">

Note that the search button should only be clickable when something has actually been typed into the search box. You wouldn't want someone searching an empty string, right?

The JavaScript Way

Ordinarily, some quick JavaScript can be used to do this, for example:

inputElement.oninput = function(e) {
    if(inputElement.value != "") {
    } else {

The Cool-CSS-Trick Way

In my opinion, there's a more optimal way to accomplish this, without Javascript, using the :not(:placeholder-shown) CSS pseudo class. There are two parts of the pseudo class: :not() and :placeholder-shown.

  • :placeholder-shown — is active when the placeholder in an input box is shown. When the input box is empty, the placeholder will be shown, and when the user types something in, the placeholder won't be shown.
  • :not() — takes an argument of what selector(s) the style should not apply to.

So, :not(:placeholder-shown) simply means applying a style to an input element when the placeholder isn't shown; meaning that styles will only apply when the input box isn't empty.

We can combine this with the + CSS operator to make our search button functionality:

button {
    display: none;

input:not(:placeholder-shown) + button {
    display: block;

Here, the button will only display when the input has content, which works exactly like the JavaScript version, just... without JavaScript.

GIF Video of :not(:placeholder-shown) Demo

Another Interesting Way to Use This

We can also combine this with the :focus pseudo class so that a style is only applied when the user is typing within an input box, like this:

<input type="text" placeholder="type something">
<p id="otherElement">You are typing</p>
#otherElement {
    display: none;
input:focus:not(:placeholder-shown) + #otherElement {
    display: block;

GIF Video of :not(:placeholder-shown) Demo


This is a pretty neat trick in general, and has actually been really useful for me when building search forms, login forms, and the like. I hope you enjoyed this post, and find this CSS trick effective.

Note that the JavaScript code referenced at the beginning of this post will not work without necessary variable definitions, and that the :not(:placeholder-shown) pseudo class may not work on some web browsers, especially at the time of reading. I personally recommend checking for browser compatibility before implementing a feature in an app or website.

Thanks for scrolling.

— Gabriel Romualdo, October 2, 2019

Originally published on my personal website:

Note: I formerly wrote under my pseudonym, Fred Adams.

Discussion (30)

seanbuchholz profile image
Sean Buchholz

CanIUse shows support for :placeholder-shown as pretty solid everywhere except IE (partial) and Edge (no support). If you don't have to support either of those browsers, then go for it! Otherwise, this is still a fantastic pure-CSS technique but should probably be paired with a JS fallback if the functionality is critical.

lucasengel profile image
Lucas Engel • Edited on

I still wouldn't use it for a button (as exemplified) as you'd only be able to see it when the input is focused. For whatever reason, the user might tab away and then decide to run the search.
Accessbility-wise, it's not a good practice either. If you change the focus from the input to the button using tab, this technique would hide the button given the input is not focused anymore.
(edit: fix typo)

seanbuchholz profile image
Sean Buchholz

Those are both very good points I hadn't considered. Maybe visually show/hide the button on input focus, and then persist that state if the user has entered some input into the field?

Maybe this isn't the best example of the :not(:placeholder-shown) selector in use, but now it has me thinking about other ways this selector could be used to enhance rather than diminish accessibility.

Thread Thread
capsule profile image
Thibaut Allender

:placeholder-shown doesn't rely on focus so it would still work while navigating with the keyboard, but screen readers would still be lost if you wanted to dim the search button. Also, you'd have to use either the disabled attribute, or better, aria-disabled (it's considered bad practice to disable a button as you might not know what disabled it, so you should still be able click it and get a proper error message), but both would require some JS to dynamically change their value. So yeah, it can be a useful pseudo-class but it turns out to be tricky, rather than a "trick" ;-)

lucis profile image

It doesn't seem so neat to have a button popping out on the page all of the sudden, as it makes more sense for it to be disabled, but nice information about the placeholder-shown

xtrp profile image
Gabriel Romualdo Author • Edited on

The "display: none;" style on the button is just a possibility: it may have been better to simply make the button slightly transparent initially, and have it be opaque when the user has typed something, but of course, there are so many ways to implement this.

For example, I am currently building a password manager, which uses the placeholder-shown trick to display an arrow icon for entering the password-vault when the user has typed content into the password field.

Password Manager Placeholder Shown Demo

abhinav1217 profile image
Abhinav Kulshreshtha

This is more practical implementation of the example in the article. I had used javascript for this effect in past projects. Do you have codepen for this?

Thread Thread
xtrp profile image
Gabriel Romualdo Author • Edited on

Yes, I do!, see line 96 of CSS to see the :not(:placeholder-shown) trick in action. As I said, this is part of a password-manager desktop application I am currently building, which is open sourced on GitHub as well.

— Gabriel

pavelloz profile image
Paweł Kowalski • Edited on

According to usability experts, buttons should not appear and disappear, especially the crucial ones.


mamrezo profile image

You can float it through the input (position: absolute) and padding the input for preventing text go behind the button.....

nikitaneganov profile image

I actually have 2 thoughts about this - first, is that actually better that validation? especially in the case when it is a login form that requires some front-end validation anyway?

Secondly, how do you handle hitting enter than? By default, input element is also submitted by pressing enter and as far as I know, there is no way to disable that without JS

xtrp profile image
Gabriel Romualdo Author • Edited on

In my experience, this trick can be applied to a vast array of things, not just forms that require validation. In the case with login form, of course, I wouldn't recommend using this trick, as the validation wouldn't be covered by :not(:placeholder-shown). In general, I've personally found this trick most useful in search forms, and forms that require little frontend validation such as a text box and button for posting a comment in a comments section.

Your second question is a great one, and brings up a point that I really haven't thought of that much myself. Personally, I would just disable the submit-on-enter functionality via JavaScript (as you said) and use the CSS trick on the side as well, but there may be a pure CSS way to accomplish this. Sorry that I couldn't provide a better answer, but great questions regardless.

jlizanab profile image
José Lizana

//you can also simulate a disabled button

button {
background-color: blue;

input:not(:placeholder-shown) + button {
pointer-events: all;

mgrubinger profile image
Martin Grubinger

I am using this trick to move around <label>s and such. I love it, so much better than dealing with focus/blur stuff in js.

adnanbabakan profile image
Adnan Babakan (he/him)

This is so cool. I always try to avoid unnecessary JavaScript and use CSS instead if possible. And this is going to come in handy in my projects. Thanks for sharing this.

lishine profile image
Pavel Ravits

All the Css people :) won't love what I say.
My opinion, state should stay in the JavaScript realm as much as possible. State should be in one place!
It is ashame that css state is even promoted as a good thing. When a Js developer comes to develop feature, he will be surprised to find state in Css left there by a loving Css developer. And then, he will have to live with it or migrate it to Js.

joel profile image
Joel Krause

This is pretty cool! I didn’t know that this existed. Pushing it into the memory bank for future projects 🎉

diogoca profile image
Diogo Alves

I didn't know... thanks for share, so useful

iamnrjstar profile image

Really!! Easy trick with CSS than the JavaScript thanks for sharing

benavern profile image

I've used this trick to create a material input with only html & css, you can see it on my personal site (in french) here :

ejoo profile image
Ejaz Karim

Thanks for writing this. Even if it useful for the use-case you've exemplified but it can be used in other cases.

najibla1 profile image
Na la

This is nice to know but I can't see myself using IRL.

leandroruel profile image
Leandro RR

this is my trick to validate if a form is filled:

yveslange profile image
Yves Lange • Edited on

Very nice, thanks for the tip. I prefer to disable the button in order to not mess up the layout.

In order to achieve that I am using the pointer-events:none and the opacity to 80%

aroulhac92 profile image
Adam R

Neat trick. I havent focused much on CSS in my endeavors. I really only learned both CSS and HTML as a necessity to implement JS. Go figure. I think I'll change that.

mostafasalama profile image
Mostafa Salama

Please note that if the user clicks the spacebar, the placeholder will be hidden and the input is empty, so you need to make sure that the input has actual characters not white spaces.

lobo_tuerto profile image
Víctor Adrián

A little click-baity title. :P

cbloss profile image

That is pretty brilliant! I will agree with what other people are saying though. Always best to cover your butt with un-supported browsers. :) Thanks for sharing though!

sl4rtyb4rtf4st profile image
Andrew Millar

I often use 'enter' to complete online forms, this method does noting to block this functionality (give it a try on codepen).

kristijanmatic profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Kristijan Matic

There is not even a slight possibility that this is the most useful trick. Worst example of a click bait - and then a really bad example of the trick