Select Boxes with Style

by Castwide on 11-8-2007 • Tags: code, css, javascript5 comments

Update, 4-9-2008: The JavaScript code in this article has been modified to fix a problem with IE 6.  The corrected code is available in both the article and the accompanying download.  The changes are explained in more detail in this article.

I ran into a new obstacle in a recent Web 2.0™ application. One of its forms contained a standard select box like the following:

Notice that the seventh option's caption gets clipped because it's longer than the width of the select box. My client wanted the options to use wrapping text, so the entire caption would always be visible despite the fixed width. I added a style ruleset for the option elements, and it worked in Firefox. Internet Explorer, however, ignored the new settings completely. A quick search of MSDN confirmed the problem:

Except for background-color and color, style settings applied through the style object for the option element are ignored [in Internet Explorer].

Lacking the option to use a standard select box, my only recourse was to create my own using a combination of CSS and JavaScript.

Fortunately, thanks to radio inputs and labels, plain HTML is capable of emulating much of the basic functionality of a select box. The HTML for the new select box is as follows:


<div class="selectbox" id="myselector">
<label>
<input type="radio" name="variable" value="1" />
One
</label>
<label>
<input type="radio" name="variable" value="2" />
Two
</label>
<label>
<input type="radio" name="variable" value="3" />
<strong>Three</strong>
</label>
<label>
<input type="radio" name="variable" value="4" />
Four
</label>
<label>
<input type="radio" name="variable" value="5" />
Five
</label>
<label>
<input type="radio" name="variable" value="6" />
Six
</label>
<label>
<input type="radio" name="variable" value="7" />
This is the seventh option in the list.
</label>
</div>

The emphasis on the third option is simply there to demonstrate the select box's embedded HTML capability.

I used the following style rules to make it look more like a typical select box:


.selectbox {
display: block;
width: 200px;
height: 90px;
margin: 4px;
padding: 0;
border: 2px inset #000000;
overflow: auto;
}
.selectbox label {
display: block;
border-bottom: 1px dotted #E0E0E0;
margin: 0;
padding: 0 2px 0 2px;
font-family: Arial;
}

Here is the result:

Because the radio inputs are wrapped in labels, they can be selected by clicking on the caption instead of the radio button itself. We're already more than halfway to the finish line.

One requirement remains. We need to hide all the radio inputs and highlight the captions when they get clicked. First, here's the additional style rule for selected labels:


.selectbox label.selected {
background-color: #000099;
color: #FFFFFF;
}

When the user selects an option, the label's class name should become "selected," while the labels of all unchecked options should be set to nothing. Now we need a bit of JavaScript to control the highlighting:


// This script requires Prototype (http://prototypejs.org)

var Selectbox = new function() {
var onClickInput = function(e) {
var inp = Event.element(e);
var box = inp.container;
highlight(box);
}
var highlight = function(box) {
var nodes = box.getElementsByTagName('input');
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].checked) {
nodes[i].up('label').className = 'selected';
} else {
nodes[i].up('label').className = '';
}
}
}
this.enable = function(elem) {
var div = $(elem);
var labels = div.getElementsByTagName('label');
for (var i = 0; i < labels.length; i++) {
var l = $(labels[i]);
var inp;
if (l.htmlFor) {
inp = $(l.htmlFor);
} else {
inp = l.down('input');
}
if (inp) {
inp.label = l;
inp.container = div;
inp.style.display = 'none';
if (Prototype.Browser.IE) {
Event.observe(l, 'click', function(e) {
var lbl = Event.element(e);
var inp = (lbl.htmlFor ? $(lbl.htmlFor) : lbl.down('input'));
if (inp) {
inp.click();
}
});
}
Event.observe(inp, 'click', onClickInput);
}
}
highlight(div);
}
}

With the above script included in the page, we can add the last of the select box's functionality with one line of code:


Selectbox.enable('myselector');

...where 'myselector' is the ID of the select box's containing div.

Here is a complete demo:

If you need a select box that allows multiple selections, you can simply use checkbox inputs instead of radio inputs. The download at the end of this article includes an example.

This solution degrades gracefully into a standards-compliant set of radio inputs. Without the CSS and JavaScript, it still retains a minimum level of useability, including for form submissions.

Download the source and sample code (including the required Prototype library): http://dev.castwide.com/distro/selectbox.tar.gz

Comments

It is unfortunate. There are so many styling tricks that would make a select list nice, but none work in IE. Another bug report is here: no styling http://webbugtrack.blogspot.com/2007/11/bug-291-no-styling-options-in-ie.html no disabled: http://webbugtrack.blogspot.com/2007/11/bug-293-cant-disable-options-in-ie.html and no events: http://webbugtrack.blogspot.com/2007/11/bug-280-lack-of-events-for-options.html PS Your comment box is incredibly small and hard to type in! ;-)
Between select options with crippled style support and weird button behavior, forms in IE leave a lot to be desired. In IE 7, at least buttons behave a _little_ more logically. Thanks for your comments. I've made the comment box bigger and made it possible to use Markdown for formatting :)
Just letting you know that this doesn't work in IE6. Basically everything looks fine, except you can't select an option, proving it to be useless. Works well in other browsers though.
Strange, I thought I had tested it in IE6. I'll take a look at the code and post an update if I can fix it.
The JavaScript has been updated to work in IE 6, IE 7, and Firefox 2. Thanks, Ben.

Add Comment

More Articles