Styling input placeholders with CSS

HTML5 and placeholders

HTML5 gave us many wonderful things. And in this case, the grass was really greener on the other side. After paddling our small HTML boat over to the grand island of HTML5 we set up camp and decided to stay, for life (or until some other even cooler island - HTML6 anyone!? - floats by).

One of many wonderful things was that we could toss out all those onfocus and onblur JavaScript combos that toggled some informative text in forms before they were filled in. Sure we had labels, and even lines of help text, but sometimes a placeholder was just right for UX and overall design (and semantics).

Old school versus new school

Remember the horrors of old? Let’s take a trip down memory lane. This is how I used to “fake” placeholders with JavaScript (true story) in the age when dragons still roamed the lands and everyone travelled by horse (a few years ago ... trust me):

<input type="text" name="mahfieldyo"
  value="A brilliant placeholder"
  onfocus="if (this.value=='A brilliant placeholder') this.value='';"
  onblur="if (this.value=='') this.value='A brilliant placeholder';"
Screen Shot 2016-06-29 at 09.39.58.png
This is how my old school placeholder looked
<input type="text" name="mahfieldyo"
  placeholder="A brilliant placeholder indeed">
Screen Shot 2016-06-29 at 09.39.53.png
New school is "same same but different" (much better)

Your design task

So the story goes like this - you get a design, from a designer. And as we all know, they sometimes tend to design impossible things, things not meant for the web (damn you Photoshop). But things progress, and with time we suddenly have new super powers in CSS. Remember all those round corners about 6-7 years ago that were almost impossible before CSS3 (hello 3x3 cell tables with images in each corner)?

The design versus what you can build.

You need a black semi-transparent (50%) background with a white colored text (opaque). Easy. You try the CSS' color property on the input field. Doesn't work. The placeholder will default to gray (a washed out white color). But you want it to be clear white, just like when you type text in there. You give up and cry a little bit. Fear no more. The solution is not far away!

You’d think that this really is something that is impossible. The big browser vendors sat down and said “Our way or the highway, son”, and we be all like “Yes, ok Sir, sorry for bothering you”.

But no, this is not the case this time. There is no Hersey highway you need to take. Let me show you how magically easy you can change the style of a placeholder text. Let pseudo elements (and classes) lead the way to glory and fame. But also, let vendor specific implementations hurl shots at you along the way (rest assured, we will reach the other side alive).

The code

Our new friends to get acquainted with are: ::-webkit-input-placeholder, :-moz-placeholder, ::-moz-placeholder and :-ms-input-placeholder.

To mix things up for us, they interchange between using one colon (pseudo-class) and two colons (pseudo-element) in the beginning. Because … why not?

Chrome, Safari, Opera and even Edge will listen for the webkit vendor tag, older IE (10+) for the ms vendor tag, and Firefox for the moz vendor tag. Easy peasy. So with these “tools” our design will work everywhere *.
* Not really everywhere, but close enough for me to say “everywhere” without being called a complete liar. Who cares about IE9, Firefox 3, and other legacy browsers anyways? Oh, you do?! Then I feel sorry for you (but also laughing a little bit at the same time, like when people walk into a lamp post, or they slip on a banana peel).

Let’s look at them in action. This here is them magic lines to fix it all:

::-webkit-input-placeholder {
	color: white;
:-moz-placeholder {
	color: white;
	opacity: 1;
::-moz-placeholder {
	color: white;
	opacity: 1;
:-ms-input-placeholder {
	color: white;

Not bad. That's it. Just copy pasta and give it a taste!

There are some details to explain though. Keep reading.

Vendor specifics and pitfalls

Firefox has different implementations of this spread throughout their versions, hence the almost duplicate definitions with “:” and “::” (double-colon is the latest and greatest implementation).

A catch with this code is that you cannot refactor these into one joined group in CSS, because if one browser doesn’t understand all of the lines it will ignore all of the rules in it, even the lines it does understand. So you must go for all four of them as separate groups, like in my example. Hey, don’t shoot the messenger!

Also, Mozilla’s implementation lowers the opacity of the text, so you need to “reset” it manually to get it to look just right (with opacity: 1;). After that, you’re good to go.

And of course you can be more specific than that and only change placeholder design on specific fields by prepending these pseudo classes with the class name of your choice.

Want more?

Read this brilliant Stack Overflow answer for more details about vendor support and such.

Need more tricks to fuel that CSS fire of yours? Check out how you can override that ugly yellow default background on pre-filled input fields in Chrome.

We’ve explored the deep dungeons of CSS before and found that we can access almost anything you see in your browser and shape it to your liking. But placeholder text in forms, that can’t possibly be styled, right? Right! … wrooong! Let me show you how to use CSS to make your placeholders look pretty again.

Continue reading »


Beautify your Form with Material Design

“Once upon a time there was an Ugly Form. Every day it would look at beautiful forms residing peacefully on the endless pastures of the Internet and sigh with envy.

Don’t I deserve my share of HTML happiness?’ the Form thought.  ‘Why do users shriek in disgust every time they see me? Why do they look terrified (and sometimes cry) when filling out my fields? And why the hell do they wash their hands after clicking my flabby lifeless buttons?””

Every time I would tell this amazing fairytale to my kids before their bedtime, they’d ask me: “Daddy, but why can’t the Ugly Form be happy too? Sure, it looks like HTML got diarrhea and pooped out a pile of colorless Lego bricks, but maybe there’s a chance for it in our cruel world?

And one day I finally decided to play the Fairy Godmother to the Ugly Form and help it turn into the Kim Kardashian of forms overnight (with zero plastic surgery expenses, mind you). After some thorough research I picked Material Design Lite (MDL) as my magic wand and that’s the only thing you will need, too.

I'll get a bit ahead of myself and show you right away what will be the end result of what we're going to do in this article.  


Looks modern and professional, right? But it hasn't always looked like that. In fact, I wouldn't dare to show you how this form initially looked if it wasn't for the sake of this article.

Anyway, let's get to the process. To begin with, we need a web page with an ugly form. I assume you already have it, but if not - just create one and experiment with it. For this article I created a job application form for an imaginary company hiring IT specialists, see below:


The page has some basic styling, mostly to add some padding to controls in the form, but nothing fancy. It’s totally fine if your page is already using some CSS classes. But be aware that they may cause conflicts with the MDL stylesheets, so you might want to tweak the code and remove the old classes (you can do that dynamically using the Javascript code below, too).

When you open that page in a browser, it should look something like this:

One Ugly Form

This form has some basic text input fields, a textarea, a table, several fieldsets with checkboxes, radio buttons and a list of bullet items. And the buttons, of course.

When I saw the ugly creature I just built with my own two hands I was like (in heavy Austrian accent): “YOU ARE ONE UGLY MOTHE**UCKER…”.

Without further ado, let’s rush to the uneasy task of turning this freak of HTML nature into something worth showing to your boss before asking for a pay raise.

First thing we need to do is add external references to the MDL’s js-library and CSS inside the <head> section of your webpage:

<!-- MDL references -->

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

<link rel="stylesheet" href=“https://code.getmdl.io/1.1.3/material.indigo-pink.min.css">

<link rel="stylesheet" href=“https://rawgit.com/MEYVN-digital/mdl-selectfield/master/mdl-selectfield.min.css">

<script defer src="https://code.getmdl.io/1.1.3/material.min.js"></script>

<script defer src="https://rawgit.com/MEYVN-digital/mdl-selectfield/master/mdl-selectfield.min.js"></script>

Alternatively, you can download the MDL package, host it on your own server and reference that instead.

Note name of the CSS file: material.indigo-pink.min.css. The “indigo-pink” part defines primary and accent colors your controls will be using. There are plenty of colors to chose from, but I picked “indigo” because it sounds mysterious and “pink” because everything beautiful is pink (for example, unicorns and €50 bills).

Now let’s create some magic. We need to write javascript code that will loop through controls on the page and apply MDL styles to them. Copy the piece of the code below and paste it inside the <head> of your page, right after the references section:


Look at the code above.

There’s a method called materializeControls which will be called in window’s onload event handler, when the DOM is in place. materializeControls calls another method called materializeTextInputs, which loops through all text inputs and textareas on the page and assigns required MDL CSS classes to them, their labels and their parent divs.

NB! In order for Material guidelines to be entirely fulfilled, each input control must be properly wrapped inside a parent div along with its label. The code will not fail if it’s not the case but "you may not be 100% satisfied with the result", as my hairdresser used to say before I had given up getting haircuts.

When you refresh the page after adding this piece of code, you will see some amazing transitions:

Materialized text inputs

Note how the first three text inputs on the left and the textarea on the right are now rendered according to the Material guidelines with more air around them, labels inside placeholders and nice on-focus highlighting.

By now you are supposed to be completely hooked, like a housewife addicted to Candy Crush, and cry for more.

We will stick to the same algorithm for other controls as well.


Add a new method called materializeSelects that will basically use the same formula as materializeTextInputs - going through select controls and applying MDL styles to them.


The only manual thing we will have to do here is add class “mdl-selectfield—floating-label” to the wrapping div of the select element. This will make sure that a dropdown’s label is shown above the control once a value is selected.

<div class="mdl-selectfield--floating-label">


<select name="education">



Refresh the page to get another injection of pure magic:

Materialized dropdown

Radio buttons

The code for radio buttons is a bit different because they are wrapped inside their labels (so that a mouse click on a label would select the button), but the principle is the same. Note how we apply “mdl-js-ripple-effect” class to radio buttons’ labels to achieve, well, ripple effect. You don’t have to do that but it adds an extra cool touch to user interaction with the elements.


Materialized radio buttons


Exactly the same principle here as with radio buttons (yes, you can use the same method with arguments):


Materialized checkboxes



Materialized table


For lists (<ul> element) we will perform a little trick. To liven up the list of offices we will replace the bullet character with a “home” icon from the huge library of Material icons.


Note how when browsing through <li> elements inside each <ul> we inject an icon before the list item’s text and then wrap both of them with a <span>:

liEl.innerHTML = "<span class='mdl-list__item-primary-content'>" +
                  "<i class='material-icons mdl-list__item-icon'>home</i>" +
                  liEl.innerText + "</span>";

In order to be able to use Material icons on your page, you need to include a reference to their font family from the Google site, but we have already done it: 

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

After that you can render any icon from the Material library like this (we used “home” as an icon Id):

<i class=“material-icons"><icon Id></i>

And that’s how our new list will look now:

Materialized list



There are many different styles and effects that can be applied to buttons; you can read about it on the MDL site. We used the same “mdl-js-ripple-effect” class to get the ripple effect whenever a button is clicked and “mdl-button—colored" class to have them colored in the primary color of our selected scheme (remember indigo?). If you replace the latter with “mdl-button—accent” the buttons will be in accent color (in our case - pink).

Materialized buttons


Believe it or not, but we’re done. Using almost no CSS and only basic knowledge of Javascript, we turned our ugly duckling into a beautiful indigo-pink-ish swan. We could have refactored our Javascript code a little to have just one pass through all elements on the page and then dispatch processing to other methods based on element type, which would of course be much better performance-wise, but here I tried to visualize “converting” controls type by type.

And this is how our form looks after our changes:

Screen Shot 2016-06-23 at 00.26.18.png
Materialized form

For even better effect I will show you the same form “before” and “after”, side by side:

Screen Shot 2016-06-23 at 00.10.16.png
The Ugly Form before and after the changes

And here's the final source code of our now beautiful form:


I hope that this article will help you to take your first steps into the beautiful land of Material Design. It’s not as scary or complicated as you may think and along the way you might even help a page or two become better versions of themselves without giving it too much effort. After all, each of us had our encounter with an ugly form even if we chose to keep it a secret.

Material Design is a hot topic nowadays. There are many who have heard of it but not so many used its guidelines in their work. It looks sexy and stuff but how do you inject all that beauty into your website? This article will explain how to apply Material Design look and feel to forms on your existing web pages using basic knowledge of JavaScript and a 3rd-party library called Material Design Lite.

Continue reading »