Spring Sale! Save 30% on all books w/ code: PLANET24
Web Dev + WordPress + Security

Better CSS Placeholder

I haven’t seen anyone mention this little CSS tip. All the proprietary vendor-specific placeholder rules now safely can be replaced with just ::placeholder. Seems very useful especially with the ever-increasing emphasis on site performance. The end result is less code and thus faster loading, better SEO and so forth.

Contents

5 second summary

Instead of this widely used monstrous vendor-specific anti-pattern:

::-webkit-input-placeholder {  /* Chrome and Safari */
	color: #777;
	}

:-moz-placeholder {            /* Mozilla Firefox 4 - 18 */
	color: #777;
	opacity: 1;
	}

::-moz-placeholder {           /* Mozilla Firefox 19+ */
	color: #777;
	opacity: 1;
	}

:-ms-input-placeholder {       /* Internet Explorer 10 - 11 */
	color: #777;
	}

::-ms-input-placeholder {      /* Microsoft Edge */
	color: #777;
	}

We now can just write this:

::placeholder { color: #777; opacity: 1; }

And done. That line supports all major browsers. So we just saved some bandwidth and boosted performance in like 2 seconds. Less code, cleaner code. Thanks CSS devs and browser makers.

Tip: In the above code, the opacity property is included for Mozilla because browsers like Firefox decrease the opacity of placeholder colors by default. For more information, check out how to deal with Firefox later in the article.
Note: “All major browsers” excludes IE, which has been retired. We’ll look at how to support IE later in the article.

Code discussion

The above vendor-prefixed anti-pattern is very common even today:

::-webkit-input-placeholder {  /* Chrome and Safari */
	color: #777;
	}

:-moz-placeholder {            /* Mozilla Firefox 4 - 18 */
	color: #777;
	opacity: 1;
	}

::-moz-placeholder {           /* Mozilla Firefox 19+ */
	color: #777;
	opacity: 1;
	}

:-ms-input-placeholder {       /* Internet Explorer 10 - 11 */
	color: #777;
	}

::-ms-input-placeholder {      /* Microsoft Edge */
	color: #777;
	}

Five declaration blocks to style the placeholder element. Looking at it now feels wrong, but alas it did the job, got us through some dark times. And you can still go that route; although a royal mess, that set of rules continues to work just fine if for some reason you need to support very old browsers.

Hmm.. Ironically the actual ::placeholder pseudo-element is not included in the commonly used anti-pattern (although it should have been). Including it would have made for a smoother transition over time.

You might think, combining all the selectors would help, something like:

/* Don't do this it doesn't work */

::-webkit-input-placeholder,
:-moz-placeholder,
::-moz-placeholder,
:-ms-input-placeholder,
::-ms-input-placeholder {
	color: #777;
	opacity: 1;
	}

Unfortunately that syntax is not supported. When it comes to styling the placeholder, you have to define each selector individually. Combining is not allowed. So if you want to customize placeholders for multiple elements, the number of declarations increases by a multiple of five.

Let’s look at an example using my pro WordPress plugin, SAC Pro. I wanted to style the placeholder for two different elements, so would have needed 10 declarations, like:


.sacpro-box  ::-webkit-input-placeholder { color: #777; }
.sacpro-form ::-webkit-input-placeholder { color: #333; }

.sacpro-box  :-moz-placeholder { color: #777; opacity: 1; }
.sacpro-form :-moz-placeholder { color: #333; opacity: 1; }

.sacpro-box  ::-moz-placeholder { color: #777; opacity: 1; }
.sacpro-form ::-moz-placeholder { color: #333; opacity: 1; }

.sacpro-box  :-ms-input-placeholder { color: #777; }
.sacpro-form :-ms-input-placeholder { color: #333; }

.sacpro-box  ::-ms-input-placeholder { color: #777; }
.sacpro-form ::-ms-input-placeholder { color: #333; }

And it just gets crazier the more elements you want to style. So much code for something so simple.

Notice the above CSS rules are all vendor-prefixed selectors, implemented to support placeholder in various browsers until full support is rolled out. Well good news, that day finally has arrived..

A better way..

Fortunately browser support for the actual CSS placeholder selector has improved greatly. In fact, recent versions of all major browsers fully support ::placeholder. So now we can style placeholders with a single golden rule:

::placeholder { color: #777; opacity: 1; }

Compare that with the ol’ vendor-prefix stack. Much less code & easier to maintain.

Or if you need to target placeholder for a specific element, say .example:

.example ::placeholder { color: #777; opacity: 1; }

And to really drive it home, let’s return to the SAC Pro example. It’s now possible to style two separate placeholders using only two lines instead of 10:

.sacpro-box  ::placeholder { color: #777; opacity: 1; }
.sacpro-form ::placeholder { color: #333; opacity: 1; }

Elegant and awesome.

Dealing with Firefox

Note the inclusion of opacity in the above examples. That helps to normalize the color property across browsers. For example, Firefox lowers placeholder opacity by default. This can be addressed directly by including the vendor-specific selector for Mozilla/Firefox:

/* Firefox lowers placeholder opacity by default */
::-moz-placeholder { color: #777; opacity: 1; }

Fortunately it’s NOT necessary to include that vendor-specific rule.

Instead, to address Firefox’s weird placeholder opacity tweaking, simply include opacity when declaring ::placeholder. The color then will be accurate and consistent across all browsers, exactly as specified.

::placeholder { color: #777; opacity: 1; }

Dealing with IE

Internet Explorer (IE) has been retired. Some people are still using IE though. According to this source, IE still enjoys 28 million users in 2023. Read it again.

So to be extra safe for those folks you could do like this. Basically including the IE vendor rule whenever using ::placeholder. For example:

/* All major browsers */
::placeholder { color: #777; opacity: 1; }

/* Internet Explorer */
:-ms-input-placeholder { color: #777; opacity: 1; }

Personally, I’m no longer adding special/extra support for anything IE. Anyone still using IE imho is gonna be just fine without my custom placeholder styles lol.

Tip: You can inspect the shadow DOM to find any applied placeholder styles.

About the Author
Jeff Starr = Fullstack Developer. Book Author. Teacher. Human Being.
BBQ Pro: The fastest firewall to protect your WordPress.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
BBQ Pro: The fastest firewall to protect your WordPress.
Thoughts
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
2024 is going to make 2020 look like a vacation. Prepare accordingly.
First snow of the year :)
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.