Recently I have been asked by my client to some custom styling on form elements. As you know we have no issues (well, at least no major issues) when it comes to prettifying input fields, text areas and buttons. But the form I needed to apply custom design to contained couple of select elements. Now this is something that's not that simple.
I always aim for the simplest solutions possible in everything I do, not just work related. I enjoy having short, few lines scripts, reduced markup etc. That is why I didn't opt for some of the ready made solutions we have out there. I rather tried to come up with the solution of my own.
Take a look at the demo or Download files
How it works
The solution I am talking about here is actually a workaround, trick. It works in a way that it dynamically adds an additional SPAN element positioned absolutely below the SELECT element. This SPAN has a custom graphic that we want to apply. SELECT element's opacity is set to zero so it is not visible but it's clickable. Since the SELECT element is not visible, what we see actually is the SPAN below.
This solution doesn't style the OPTION dropdown, only the default appearance of the SELECT element but considering the simplicity I (and my clients :) ) believe that it is very applicable.
Important thing to remember: this trick relies heavily on absolute positioning. Newly created SPAN element will position itself in relation to parent element (DIV in my case). If you have other stuff inside the parent element, things like text, labels etc. make sure that you position the newly created SPAN accordingly.
Also, as with any other project I am working on, I used jQuery as the library of choice.
The script
Here is the entire script:
$(document).ready(function(){
if (!$.browser.opera) {
$('select.select').each(function(){
var title = $(this).attr('title');
if( $('option:selected', this).val() != '' ) title = $('option:selected',this).text();
$(this)
.css({'z-index':10,'opacity':0,'-khtml-appearance':'none'})
.after('<span class="select">' + title + '</span>')
.change(function(){
val = $('option:selected',this).text();
$(this).next().text(val);
})
});
};
});
Script, line by line explained:
$(document).ready(function(){
Script executes on DOM load.
if (!$.browser.opera) {
Had some issues with transparency in Opera so I decided not to support Opera for this trick.
$('select.select').each(function(){
What follows will apply to every SELECT element with the class name select
var title = $(this).attr('title');
Each SELECT element should have TITLE attribute set to whatever we want to show as a default value of the drop down. We are storing the value of the TITLE attribute in a variable for further usage.
if( $('option:selected', this).val() != '' ) title = $('option:selected',this).text();
Checking if any of the options is selected by default. If it is we will use it as a default value. If not, we are using the previously stored TITLE attribute value.
$(this)
.css({'z-index':10,'opacity':0,'-khtml-appearance':'none'})
For each of the SELECT elements we are setting the z-index to anything above the value of 1, opacity to zero, and we're also removing the default styling for Safari.
.after('<span class="select">' + title + '</span>')
We are then adding a SPAN element that have background image set in CSS and is placed exactly below the SELECT element.
.change(function(){
val = $('option:selected',this).text();
$(this).next().text(val);
})
With every change of value for the SELECT elements we are updating the SPAN element inner text.
HTML/CSS source code
Just as a script, proper markup and CSS is very important to make this to work. SELECT elements needs to be wrapped inside a parent element (DIV in my case) that has a position property set to relative, so the newly created SPAN can be properly positioned.
This is the markup for the SELECT element:
<div>
<select class="select" title="Select one">
<option></option>
<option>Blue</option>
<option>Red</option>
<option>Green</option>
<option>Yellow</option>
<option>Brown</option>
</select>
</div>
Note the TITLE attribute. Script will use it as a defautl value.
CSS looks like this (some comments included):
/* all form DIVs have position property set to relative so we can easily position newly created SPAN */
form div{position:relative;}
/* setting the width and height of the SELECT element to match the replacing graphics */
select.select{
position:relative;
z-index:10;
width:166px !important;
height:26px !important;
line-height:26px;
}
/* dynamically created SPAN, placed below the SELECT */
span.select{
position:absolute;
bottom:0;
float:left;
left:0;
width:166px;
height:26px;
line-height:26px;
text-indent:10px;
background:url(images/bg_select.gif) no-repeat 0 0;
cursor:default;
z-index:1;
}
Try the demo, download the files and of course let me know what you think :)

Thomas Svensson 7 Sep, 2010
Mladen Stepanic 7 Sep, 2010
http://emforma.rs/temp/t14/index2.html
Pippin 7 Sep, 2010
cssglobe 7 Sep, 2010
For non JS clients everything will remain as is, no styling applied.
Davor 7 Sep, 2010
IGotNothin 7 Sep, 2010
Matt 8 Sep, 2010
Carlos 8 Sep, 2010
I've made a hard choice doin' this:
http://www.bhshopping.com.br/
look at the "select in "BUSCAR POR LOJA"
it would be nice if the form elements were that easy to style...
Mike 10 Sep, 2010
Wael Al-Sallami 12 Sep, 2010
ANdRei™ 12 Sep, 2010
Mathias 12 Sep, 2010
Diti 12 Sep, 2010
Jonathan 12 Sep, 2010
This script is really cool, although the initial flash reminds me of the @font-face text flash. I'd definitely use this if it got rid of that flash.
Ricardo 13 Sep, 2010
XingWoo 13 Sep, 2010
www.real-anonymity.es.tc
Thany 13 Sep, 2010
Volomike 13 Sep, 2010
Ritu 14 Sep, 2010
cmacias 19 Sep, 2010
http://www.cmacias.com/cambiando-el-aspecto-de-los-selectbox/
or
http://www.cmacias.com/mejorando-los-selectbox/
or multiple
http://www.cmacias.com/selectbox-multiple/
And how to change the input type file part 1.
http://www.cmacias.com/maquillar-un-input-file-upload/
and part 2
http://www.cmacias.com/maquillar-un-file-upload-2/
Beben 22 Sep, 2010
Ben Stokes 25 Sep, 2010
algerien-dev 26 Sep, 2010
http://www.filamentgroup.com/lab/jquery_ui_selectmenu_an_aria_accessible_plugin_for_styling_a_html_select/
is pretty nice too 0_^
Antti202 29 Sep, 2010
tildy 30 Sep, 2010
Web Designer Leicester 30 Sep, 2010
David Christian-Woodruff 6 Oct, 2010
It's not always the first thing that people think about when designing a web page, or indeed even if they do, and so having something that enables them to style Select elements is an excellent addition to the process.
What's more is that it certainly makes a page look more clean and professional, something that clients will pick up on when viewing a design for the first time.