How To Style a Select Dropdown Using Only CSS

UI form elements, such as select dropdown lists, have always been difficult to design in CSS. The issue is based on the fact that UI form elements are not necessarily part of the web standard specs. This also includes other form elements such as radio buttons, checkboxes, etc.

However, select dropdown lists are one of the trickiest to design with CSS alone and have no consistency in various browsers when doing so. Workarounds using JavaScript are mostly used to design around this, however, I will show you an easy way to design them using CSS.

Basic HTML

<select>
	<option>Option 1</option>
	<option>Option 2</option>
	<option>Option 3</option>
</select>

CSS

Now let’s go ahead and do some CSS styling:

* {
	margin:0; 
	padding:0; 
	-moz-box-sizing: border-box; 
	-webkit-box-sizing: border-box; 
	box-sizing: border-box;
}
body {
	background: #444;
}
select::-ms-expand {
	display: none; /* hide default arrow in IE10 */
}
select {
	width: 50%; /* Set width. Do not set height else it will fail in IE8-10. Use padding for height. */
	color: #333;
	font-weight: normal;
	font-size: 1em;
	line-height:1.2em;
	margin: 0 0 10px;
	padding: 6px 0; /* use this to set a specific height for your dropdown (DO NOT use the attribute 'height') */
	border: 0 none;
	cursor: pointer;
	text-indent: 0.01px;
	text-overflow: "";
	background: url('images/arrow.png') no-repeat 100% 4px #fff; /* add your own arrow image */
	*background-image:none; /* turn bg image for IE7 */
	background: url('images/arrow.png') no-repeat 100% 0px #fff; /* fallback bg image*/
	background: url('images/arrow.png') no-repeat 100% 0px, -webkit-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -moz-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -ms-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -o-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, linear-gradient(top, #fff, #9c9c9c);
	-webkit-appearance: none; /* gets rid of default appearance in Webkit browsers*/
	-moz-appearance: none; /* Get rid of default appearance for older Firefox browsers */
	-ms-appearance: none; /* get rid of default appearance for IE8, 9 and 10*/
	appearance: none;
}
select option {
	background: #fff; /* style the dropdown bg color */
}

Here’s how it looks:

dropdown in css

Please note: I’ve used a lot of hacks in CSS to get the desired output we want. Hacks are sometimes a necessity when dealing with older browsers, especially if it’s your only option. However, I myself try to refrain from having to use hacks as it is not best practice.

An Alternate Solution

Using the same HTML structure for the select dropdown as before, here’s an alternative way of using JavaScript/jQuery to achieve similar results:

jQuery

$(document).ready(function() {

$('select').each(function(e) {
	var selE = $('select:eq(' + e + ') option:selected').text();
	$(this).wrap('<div class="selectWrap"></div>');
	$('.selectWrap:eq(' + e + ')').append('<span class="selectInner"></span>');
	$('.selectInner:eq(' + e + ')').text(selE);
});
$('select').change(function() {
	var i = $(this).index('select');
	var sel = $('select:eq(' + i + ') option:selected').text();
	$('.selectInner:eq(' + i + ')').text(sel);
});

});

HTML Ouput

And here’s the output. Notice that the jQuery script wraps the select dropdown in a div with a class of ‘selectWrap’ and also adds a span with a class of ‘selectInner’ which we will use to style our elements:

<div class="selectWrap">
<select>
	<option>Option 1</option>
	<option>Option 2</option>
	<option>Option 3</option>
</select>
<span class="selectInner">Option 1</span>
</div>

CSS

Now let’s style it with CSS:

* {
	margin:0; 
	padding:0; 
	-moz-box-sizing: border-box; 
	-webkit-box-sizing: border-box; 
	box-sizing: border-box;
}
body {
	background: #444;
}
.selectWrap {
	display:block;
	width: 50%; /* Set the width of the entire select dropdown  */
	height: 34px;
	margin: 0 0 10px;
	padding:0;
	position:relative;
}
span.selectInner {
	position:absolute;
	display: block;
	margin: 0;
	padding: 0 0 0 5px;
	width: 100%;
	height: 34px; /* set same height */
	line-height: 34px; /* set same height */
	color: #333;
	white-space: nowrap;
	overflow: hidden;
	text-align: left;
	text-overflow: ellipsis;
	font-weight: normal;
	font-size: 1em;
	z-index:1;
	background: url('images/arrow.png') no-repeat 100% 0px #fff; /* fallback bg image*/
	background: url('images/arrow.png') no-repeat 100% 0px, -webkit-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -moz-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -ms-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, -o-linear-gradient(top, #fff, #9c9c9c);
	background: url('images/arrow.png') no-repeat 100% 0px, linear-gradient(top, #fff, #9c9c9c);
	-webkit-border-radius: 4px;
	-moz-border-radius: 4px;
	-ms-border-radius: 4px;
	-o-border-radius: 4px;
	border-radius: 4px;
	-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.3);
	-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.3);
	-ms-box-shadow: 0 1px 3px rgba(0,0,0,0.3);
	-o-box-shadow: 0 1px 3px rgba(0,0,0,0.3);
	box-shadow: 0 1px 3px rgba(0,0,0,0.3);
	}
select {
	width: 100%;
	height: 34px; /* set same height */
	position:absolute;
	left: 0;
	z-index:2;
	padding:0;
	margin:0;
	border:0 none;
	float:none;
	opacity:0;
	cursor: pointer;
	-webkit-appearance: menulist-button;
}

here’s the output:

dropdown using JS

Conclusion

As you can see, there are multiple ways of designing the select dropdown menus. However, please note that many browsers tend to display them differently.

I’ve included the files below for you to test out:

how-to-style-select-dropdown-using-css

UPDATE: 06/11/2014

Just recently, a bug was reintroduced with Firefox 30.0 that makes it so that the default arrow on the select dropdown will still show up. As of writing, there is still no CSS fix to address the issue. For more information on this, visit the Firefox bug tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=649849

9 thoughts on “How To Style a Select Dropdown Using Only CSS

  1. Hello Alfonse!

    I was thinking of using your dropdown list for donations, allowing people to choose between $10-$20-$50, etc, and was wondering how I might trigger an event? I was thinking of using Stripe Checkout so that when a person clicks $10, the stripe overlay will appear on-click.

    For an example of the Stripe Checkout overlay: http://jsfiddle.net/wRHKB/

    Do you know if it’s possible to implement this?

    • Unfortunately, IE7/8/9 display the dropdown CSS only version with the default browser arrow. There is no CSS work-around for that. IE10+ displays the dropdowns properly without the default browser arrow.

      Your best bet would be to use the alternate jQuery method I proposed. That one works on all browsers including IE6. (Please note to use jQuery version 1.9)

    • You’ll need to change the background color for the select selector in your CSS file. Or change gradient colors in the examples above.

      As for changing the dropdown text color, you’ll need to target the <option> tag and change the color property.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>