Strategies for Select Dropdown Lists Placeholder

HTML5 brings us the placeholder attribute using which we can set default text on an input field or a textarea that goes away when you focus in the field and then write something. What about placeholders for select dropdowns ?

The Problem

Now you may think that placeholders for select dropdowns makes no sense, but let me try to illustrate a bit.

What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.

Select dropdown placeholder form illustration

You can see gray placeholders in the input fields above that turn black (text) on typing something inside. But what about the select dropdown ? When you choose an option it’s text color will remain gray. For a consistent user experience I believe that the color should change (to black) when some option (other than the default one) is chosen. This is the problem we’ll try to solve with some Javascript (as I couldn’t find a full blown CSS solution).

The Solution

We can give the select dropdown a class called say not_chosen and style it in whatever way we want, to make the default option look like a placeholder, in this case just a different text color.

form select.not_chosen {
  color: #808080;
}

Next we use JS to traverse through all the dropdowns on the page and give them this not_chosen class if it has the default value chosen or if the user chooses the default value manually. We’re assuming the default value to be an empty string ''. Oh, and we’re going to use the jQuery library.

// Select dropdowns
if ($('select').length) {
	// Traverse through all dropdowns
	$.each($('select'), function (i, val) {
		var $el = $(val);
		
		// If there's any dropdown with default option selected
		// give them `not_chosen` class to style appropriately
		// We assume default option to have a value of '' (empty string)
		if (!$el.val()) {
			$el.addClass("not_chosen");
		}
		
		// Add change event handler to do the same thing,
		// i.e., adding/removing classes for proper
		// styling. Basically we are emulating placeholder
		// behaviour on select dropdowns.
		$el.on("change", function () {
			if (!$el.val())
				$el.addClass("not_chosen");
			else
				$el.removeClass("not_chosen");
		});
		
		// end of each callback
  });
}

Great! Now the dropdown will have the not_chosen class as long as the default value is chosen which means it’ll have gray color for text but as soon as it’s changed to some other option the class get’s removed and the text color fallbacks to whatever is defined in CSS for the select element (black in our case as nothing is specified).

A slight issue still persists that may or may not concern you. But if it does let’s examine it first and then try to find out a fix.

Dropdown placeholder issue

As you can see when you try to select an option when the default option is chosen, all of them are gray because that’s what we specified for our not_chosen class. On the other hand when an option with proper value is selected then all options are presented black. Maybe we want to show the first option as gray and all other as black regardless of the current choice. This piece of CSS does the trick –

form select option {
	color: #080808;
}
form select option:first-child {
	color: #808080;
}

Dropdown Issue Fix

Although on Mac all the options in the active dropdown are always black, nothing can force them to change their colors apparently.

Mac Select Dropdown

Bonus

See those radio inputs ? On selection they should also be black for consistency right ? Easy. There default style is something like this –

form input[type="radio"],
form input[type="checkbox"] {
  -webkit-appearance: none;
  display: none;
}
form label.radio:after {
  content: '';
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #d8d8d8;
  left: 10px;
  top: 10px;
}

Add some more CSS for the active state like this –

/* Turn the custom radio black */
form input[type="radio"]:checked + label.radio:after {
  background: #000;
  border-color: #000;
}
/* Turn the label text black */
form input[type=radio]:checked + label {
  color: #000;
}

Here’s the final demo:

More Options

Let’s explore a couple of other options to implement placeholders in html select dropdowns.

In a regular dropdown, you can try making the first option disabled and selected which’ll keep it selected until the user chooses another option after which it’ll appeared as a unselectable disabled option in the list.

<select>
    <option value="" disabled selected>Select your option</option>
    <option value="opt1">Option 1</option>
    <option value="opt2">Option 2</option>
</select>

Then style the disabled option like this (again doesn’t seems to work on Mac):

select option:disabled {
	color: #808080;
}

You could further add display: none; to hide the first option after a selection is made.

<select>
    <option value="" disabled selected style="display: none;">Select your option</option>
    <option value="opt1">Option 1</option>
    <option value="opt2">Option 2</option>
</select>

This approach works great on my ubuntu chrome and firefox but on Mac 10.8.2 it’s just like the previous sample, i.e., shows up the first option as a disabled one and doesn’t hides it. Here’s a testcase employing the above techniques.

Also check out Select2 and/or Chosen to show a placeholder value until a selection is made.

That’s all folks!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

3 thoughts on “Strategies for Select Dropdown Lists Placeholder”

  1. Thanks for this!

    Very clear explanation of what you can and can’t do to a dropdown and the nuances of cross browser (and Mac) issues.

    I found your jQuery code a little verbose so I condensed it down some for my own usage:


    $('select').on('change', function() {
    var el = $(this);
    el.toggleClass('unselected', !el.val());
    }).change();

    If you know your select elements are exist within a specific container you can probably get a bit better performance out of a delegate handler, but the above is a quick n’ dirty global solution.

    Thanks again!

  2. Thank you SO much! I was about to write my own script for it, when I came across yours. You saved me a good bit of time–thank you! I just plugged it in as you wrote it, and all worked great.

Leave a Reply

Your email address will not be published. Required fields are marked *