We all know that people don’t like filling out forms online, including the folks who design and build them. Most good web designers working today know to keep them as concise and painless as possible. A minimalist sign up process on your shiny new web app is sure to produce a higher sign up rate than one that asks for a dozen pieces of irrelevant information.
Sometimes, however, you’ll want to develop a form that truly benefits from a large number of options. Let’s design a search form for a fictional used automobile site. Presenting every option in your database would probably be messy and intimidating. Just one section might look something like this:

An Alternative Presentation
There may be times when keeping all of the available options visible makes the most sense. Let’s assume for the time being, however, that you want to package the search options into a neater display.

Using this technique, we’re able to save valuable screen real-estate and the user is, hopefully, less frightened by all those checkboxes. In addition, you’ll have much more freedom to style your dropdown controls to match the look and feel of your application.
Building the Widget
This technique doesn’t require a fancy graphics treatment. You could easily use vanilla HTML elements and wire up the interaction elements with Javascript (as we’ll discuss below) and you’ll be good to go. However, if you’re wanting that little extra flair, let’s jump into Photoshop (or your graphics editor of choice).
I’ve built my widget to a fixed width with the idea that it’ll be smart enough to grow taller to accommodate longer text. Here’s how the plain widget looked:

And with the dropdown “trigger”:

As I mentioned, we want the widget to be able to expand vertically so that longer text doesn’t dangle outside it. We’ll split our image into top and bottom pieces and stretch the top one out so it’s tall enough to hold the fullest possible amount of text.
Top Piece

Bottom Piece

Be sure you don’t simply resize the image to be tall enough since it will distort your masterpiece. Simply select one horizontal row, copy it, paste it, and use the transform tool to create the “filler” region.
Styling and Wiring
Now it’s time to create the HTML, CSS, and Javascript needed to make your widget come to life. In its most basic form, there is a wrapper container:
<div class="dd_wrapper">
<div class="dd_bottom"></div>
</div>
The dd_wrapper class will contain our top background image and dd_bottom will contain the bottom one.
.dd_wrapper {
color: #fff;
width: 169px;
background: url(../images/dd_top.gif) top left no-repeat;
font-size: 11px;
padding: 11px 30px 10px 14px;
position: relative;
line-height: 1.3em;
min-height: 17px;
}
.dd_bottom {
width: 213px;
height: 18px;
position: absolute;
bottom: -1px;
left: 0;
background: url(../images/dd_bottom.gif) top left no-repeat;
z-index: 0;
}
There’s nothing too fancy going on here. The width of dd_wrapper is accounting for the image width minus the left and right padding (213 - 30 - 14 = 169). The right padding is larger to allow room for the dropdown trigger graphic. The position attribute is set to relative so that we can absolutely position our other elements within in. The dd_bottom class is anchored to the bottom left of the parent container and its width is left at 213px since there is no padding for it. We specify a height of 18px to match that of the bottom image so that it doesn’t collapse and disappear due to having no inner content.
Next, let’s add our dropdown trigger and a span wrapper for our text label.
<div class="dd_wrapper">
<span class="inner">
Engine <span class="light">(6 cylinder, 8 cylinder)</span>
</span>
<a href="#" class="dd_toggle" title="Change">
<img src="../images/dd_toggle.gif" alt="Change" />
</a>
<div class="dd_bottom"></div>
</div>
The inner class will hold our text and the dd_toggle link is positioned on the right hand side.
.dd_wrapper .inner {
position: relative;
z-index: 100;
}
a.dd_toggle {
position: absolute;
top: 11px;
right: 13px;
z-index: 10;
}
.dd_wrapper .light {
color: #a3bfe9;
}
The inner class is relatively positioned so that the z-index rule works properly. These are used to keep the text above the background image of the dd_bottom container.
Now it’s time to add our dropdown panel. It will be hidden by default and the dd_toggle link will call a Javascript function to handle the showing and hiding of the panel.
<div class="dd_wrapper">
<span class="inner">
Engine <span class="light">(6 cylinder, 8 cylinder)</span>
</span>
<a href="#" onclick="toggleDropdown('engine_options');return false;" class="dd_toggle" title="Change"><img src="../images/dd_toggle.gif" alt="Change"/></a>
<div class="dd_bottom"></div>
<div id="engine_options" class="dd_option_panel" style="display:none;">
<p>Select which engine options you are interested in.</p>
<ul>
<li><input type="checkbox" id="engine_4" />
<label for="engine_4">4 cylinder</label>
</li>
<li><input type="checkbox" id="engine_6" checked="checked" />
<label for="engine_6">6 cylinder</label>
</li>
<li><input type="checkbox" id="engine_8" checked="checked" />
<label for="engine_8">8 cylinder</label>
</li>
<li><input type="checkbox" id="engine_10" />
<label for="engine_10">10 cylinder</label>
</li>
<li><input type="checkbox" id="engine_12" />
<label for="engine_12">12 cylinder</label>
</li>
<li><input type="checkbox" id="engine_hybrid" />
<label for="engine_hybrid">Hybrid</label>
</li>
<li><input type="checkbox" id="engine_elec" />
<label for="engine_elec">Electric</label>
</li>
</ul>
<p class="buttons">
<input type="image" src="../images/save_choices.gif" onclick="toggleDropdown('engine_options');return false;"/>
</p>
</div>
</div>
The toggleDropdown() function will toggle the requested panel and it will also ensure that all other panels are hidden. This way, if one panel is open and the user clicks the trigger on another dropdown widget, only the newest panel will appear as open. I am using the Prototype Javascript library here, but this could easily be adapted to any other implementation.
function toggleDropdown(panel)
{
// toggle the requested one
Element.toggle(panel);
// then hide all of the others so that only
// one (at most) is open at a time
$$('body .dd_option_panel').each(function(node){
if (node != $(panel)) {
Element.hide(node);
}
});
}
The Requisite IE Hacks
You can always count on Internet Explorer to keep you on your toes. If you choose to align your dropdown widgets vertically like I have in my example, you’ll notice that the higher dropdown panels render behind the lower widgets. This is due to IE’s z-index implementation that is documented extensively elsewhere. The fix is to wrap each dropdown container with an additional div element whose sole purpose is to force a proper z-index stack.
Also, keep observers may have noticed my use of min-height for the dd_wrapper container. IE6, of course, doesn’t support this attribute but I’ve had success using Dustin Diaz’s Min-Height Fast Hack.
.dd_wrapper {
...
min-height: 17px;
/* IE6 min-height hack: http://www.dustindiaz.com/min-height-fast-hack/ */
height: auto ! important;
height: 17px;
}
<div style="position:relative;z-index:60;">
<div class="dd_wrapper">
...
</div>
</div>
<div style="position:relative;z-index:50;">
<div class="dd_wrapper">
...
</div>
</div>
Final Touches
My example includes a save button that could be used to make an AJAX call. This would be useful if your search updated the results on the fly as search options were changed. If your form was going to be submitted normally, this button could be removed.
Keep in mind that you aren’t limited to checkbox fields in your dropdown panels. You could use radio buttons or anything else. With these types of hidden panels, you will be able to include some additional helper text for your users when it makes sense, but try to keep it short and to the point.
The final thing you’d want to add is some code to handle the updating of the text label when the options are updated. Depending on your implementation, there are various ways to handle this. For example, the result of an AJAX request might determine how the label gets updated. You might want to have your toggleDropdown() function include some logic to update those DOM elements.
My final advice would be to put a little extra thought into making the text labels smart enough to show a concise view of the selections. For example, if your user selects all of the options for Fuel, “Any Fuel” is easier to read (and actually indicates an all-inclusive selection) than “Fuel (Gasoline, Diesel, Alternative)”.
Hopefully this article gives you some ideas that you can incorporate into your next project. The overall idea is quite simple, but there are endless ways that you could expand and improve upon it!




It would be great if you could click anywhere on the widget to open it rather than just the little drop down, since the whole thing looks like a button anyway it wouldn’t hurt to have it act like one.
Really nice, but it presents something of an accessibility issue for those whose browsers don’t handle Javascript (ie: screen readers, etc).
A fallback option would be great, whereby you set the link to the same URL (rather than using the hash symbol) but specify a querystring parameter that is read server-side when the page reloads, thus expanding or collapsing the relevant boxes.
Nice Tutorial.
Like Mark said there are some accessibility issues. So I would recommend to hide the dd_option_panel via JS:
Element.observe(document, ‘dom:loaded’, function(){
$$(’div.dd_option_panel’).invoke(’hide’);
}
);
(And remove “display:none” from the HTML.)
I would also suggest to use unobstrusive scripting and add the toggleDropdown function via Event Handlers.
This way you can also avoid empty a tags and like Andrew suggests use the whole area as clickable.
$$(’div.dd_wrapper’).invoke(’observe’, ‘click’,
this.toggleDropdown.bind(this));
@Mark Steadman - Agreed
you must always have a backup option when implementing JavaScript. There should at least be a no script implementation if you are not willing to apply the lengths that Mark mentions with the querystring. The no script could show all of the check boxes (thus reverting back to original problem) but at least the form will be fully accessible.
Design wise and functionality if JavaScript is enabled the solution is very good.
I’m not sold on the demo - its basically a form in an accordion, which does save space and is themed, but what troubles me is it is hard to actually update anything.
It seems to have split one ugly form into 6 forms that are no longer accessible and added in many more clicks to get things done.
I’m sure there is a compromise between the approaches and it could be made more useful
Would have been nice if it actually worked in my browser. :) Safari 3.
This obtrusive hack really breakes my heart.
It also breakes usage of tab to navigate through a form.
Opening a set also breaks mouse-navigation because the following sets are hidden.
And disabling javascript breakes the whole thing because you can not see one input, only fancy headers.
… more an anti-pattern than a useful solution.
I think the point of this article was to show how to shorten a long form when the options themselves don’t change to much. Orbitz comes to mind where non-smoking would be the default choice, but if someone wanted a smoking room (hotel search) they could use a widget like this to get at their option. Most people would leave it alone, but for those who need it, it is there.
Good points about accessibility in the comments. I think just having the widgets styled well in CSS, and hiding the options via javascript when the page loads is a good idea. It makes more sense than building a server side component to match the look and feel.
Gmail, Google Reader, Google Calendar, Backpack, Basecamp, Netvibes, etc. etc. etc. All applications that require Javascript being on for normal clients (and have redirects for mobile clients).
Now, tabbing through the form, yes that’d be nice.
As far as Safari 3 goes, Havard, you must have some special version, b/c I tested it in Safari 3 before the article was published and it works just fine.
While I appreciate the spirit of this article - simplifying a form, the execution and overall user experience is poor.
Sure, the initial unstyled example form you use in the post isn’t going to win any design awards, but at least users are aware of all of their choices without 6-12 (or more) additional clicks to open, close and “save choices”.
Keep in mind that this is just an example UI pattern. I’m not saying that it makes sense in every situation (in fact, I’d say there are very few times when I’d use it), but it’s one more concept that can be thrown in your toolbox.
Could it be improved upon? Of course! If you’re unfortunate enough to be developing an app that requires support for no JS, then mix in some degrading magic or skip this idea all together. Consider my tutorial a starting point in case you come across a situation where it might benefit your project.
In that case it probably would have been better to stick with the UI discussion without including problematic js that users are apt to implement.
For what it’s worth, I’ve made an unobtrusive element toggle script that uses onclick and onkeypress, and also adds tabindex. Click on the newspaper add on the sidebar.
Suggestions on how to limit onkeypress to the enter key are appreciated.
[…] Dnes vyšel na Vitamínu článek ve kterém jsem náhodou narazil na skript pro snažší togglování. Nevím přesně co jejich skript dělá a jak to dělá, ale připomělo mi to můj skript pro jQuery, který by bylo fajn vylepšit. Odkazovaný článek mimochodem obsahuje kód pro Prototype. […]
One method I don’t hear often discussed is to apply a ‘has-js’ class to the body tag when the page loads. It saves you all the nonsense involved with hiding and showing certain elements, and changing one class reflows the design *significantly* faster than letting each individual JS element determine how it wants to look upon page load. For exampe:
YAHOO.util.Event.onDOMReady(function() {
YAHOO.util.Dom.addClass(document.body, ‘has-js’);
});
…
.widget .ajaxLink { display: none; }
.has-js .widget .ajaxLink { display: block; cursor: pointer; }
etcetera.
One last barely-associated thought–I would love to see very meticulous unobtrusive scripting become the norm in web tutorials. Death to onclick! The more tutorials that ditch rigid scripting archetectures, the better the quality of internet applications will become.
nick: I really like your suggestion of setting a has-js class to the body.
Is your scorn of onclick referring to onlick in general or only to instances where it is embedded in the html? My understanding is that onclick as a function is fairly accessible.
It seems like this is a solution in search of a problem. If you have such a large database with that many options, a good way to handle it is to present a number of common options, and presenting them as links thereby chopping out big chunks of the size of the return without having to make someone check or select a bunch of form fields. Carmax does a good job of this. I think people often get in the habit of thinking, well, i have to make a way to get all this stuff out of my database, let me make options for every field/combination when there are ways to get the user closer to what they want without overwhelming them.
I agree with Nick Husher. I’m getting tired of seeing web tutorials chocked full of bad practices. It always leads to the same thing… someone blasts the author, the author comes back with an excuse like “it was only a demonstration”, without acknowledging the problems that arise from JavaScript newbies copying the examples. And on a site like Vitamin, it’s especially depressing to see.
That said, I do like the overall aesthetics of the end result… just not the means used to get there.
[…] Read more […]
[…] Beautiful forms […]
[…] Vitamin Features » Streamline your forms with widgets (tags: javascript forms css design xhtml howto webdesign toread *) […]
Can anyone of you point me in the right direction on good javascript practices? since I am a newbie (websites, books.. anything would be very appreciated) thank you.
[…] Vitamin Features » Streamline your forms with widgets (tags: form webdesign css javascript xhtml) […]
This is a really good example of how not to approach building webpages in 2008. As mentioned by others the page would be impossible to use with JavaScript turned off. There is no mention of progressive enhancement and the author is happy to use inline events and styles when there is really no need to for something so simple.
I would have expected a little better editorial review to articles like this on Vitamin. Newer people to web development come here for advice, guidance and best practice to then learn and develop their own skills.
@AC
There’s some useful information on Douglas Crockford’s website. Particularly note the giant section for JavaScript. While I don’t agree with him 100%, I think 95% of what he says is quite valuable. Go through all of the links. It’s not necessarily a “best practices”, but it might get you started in the right direction.
Thank you Peter i will take a look at it.
Great article Peter. It’s a fantastic way to categorize selection fields that may either be irrelevant (in the case of an advanced search as you’ve stated) or that a user may not know at the time of data input.
[…] Vitamin Features » Streamline your forms with widgets (tags: css forms javascript) […]
[…] Streamline your forms with widgets A clever approach to streamlining a screen full of checkboxes, you might just be able to once again look fondly on your forms. (tags: javascript webdesign) […]
@AC - you could start here:
http://www.digital-web.com/articles/separating_behavior_and_structure_2/
Great idea, I’ll certainly use that next time a huge form pops into one of my projects.
The only gripe I have with this example is that you could animate it using an accordion style effect instead of having a dropdown that obscures the rest of the options.
This minimizes clicking, which should be kept to a minimum to make sure the site is usable.
It’s rather unfortunate that Vitamin would publish an article advocating such a lax approach.
I like the idea. I think it’s good UI. (In fact, Dell.com does this very thing on the computer customization screens.) It’s just a sloppy way of implementing it.
Just wanted to make a quick comment thanking everyone for their feedback on this article.
While I don’t think it’s possible to use unobtrusive JS in every project, and I do think the “what about when JS is turned off?” is a tired, overused argument more appropriate in the 90’s than it is today, for something like this it would have been relatively straight forward.
In the future we’ll make sure to focus more on unobtrusive solutions and, as always, encourage everyone’s continued feedback.
[…] I’ve just been reading a tutorial at smashing magazine. It’s a good tutorial, offering up ways to minimise the scariness of forms by grouping fields and hiding/showing them with Javascript, accordion style. […]
Nice work Scott Lenger. all with just one empty span.
[…] Follow any comments here with the RSS feed for this post. Post a comment or leave a trackback: Trackback URL. « Reminder: Speaking Tonighton Mobile […]
JQuery library could be used instead of Prototype. The JQuery version would be something like this.
the following section goes before the entire form:
$(document).ready ( function () {
$(”a.dd_toggle”).click( function () {
$(this).sibling(”div.dd_option_panel”).toggle(”fast”);
return false;
});
});
and in the form the toggler anchors must be like this and no onclick behavior or anything else..
Overall, this widget is great and glamour… nice article. will surely try to use something like this..
I want to echo other people on this thread that the code used is really poorly formed. I expect much cleaner and semantic code to come from a website that has such CSS heavyweights on its Advisory Board. “inner” divs? “wrapper” divs? Spans with the aesthetic rather than semantic class names (”light”).
Also, have you heard of fieldset?
Jason, in all honesty I think you should have just presented UI mockups and not gone into markup and CSS at all and this would be a much better article.
I would urge Vitamin to take this down and revise the code. I’ll gladly help. As a designer and developer I wouldn’t want to deal with this code on any project I was coming into.
Too bad…
I understand, Andrew, that sometimes it makes sense to choose your audience up front when developing a web app and make a decision whether or not to require javascript. But, in that respect, I think Vitamin failed to deliver to its audience here–obviously an audience of forward-thinking, unobtrusive JavaScript proponents and practitioners. It might have even been a good idea to say up front that the solution proposed here is not meant to gracefully degrade.
edit: I understand, Adam
I work with an Andrew.. my mistake
[…] Vitamin Features - Streamline your forms with widgets […]
[…] In questo articolo viene presentato un sistema per semplificare, o forse sarebbe meglio dire compattare, un form complesso. […]
[…] Vitamin Features » Streamline your forms with widgets “Using this technique, we’re able to save valuable screen real-estate and the user is, hopefully, less frightened by all those checkboxes. In addition, you’ll have much more freedom to style your dropdown controls to match the look and feel of your application.” I could have used a technique like this recently, but I was having some positioning problems so I had to ditch it. Nice walk-through. […]
[…] Vitamin Article: Streamline Your Forms With Widgets And, in the learn something new every day category, here’s an article from Vitamin about fancying up your html forms. I really hate the word widget, but it’s a handy article. Vitamin is a sort of portal-style resource for articles on all sorts of web interests (but not Flash). They’re aligned with the whole 2.0/VC/Rails contingent, but have a good staff of experienced folks writing things. Add a comment: […]
[…] You can find the ‘Streamline your forms with widgets‘ article at the Think Vitamin website. […]