Unobtrusive connected select boxes - yet another solution approach

Update#2: the third demo allows for preselect states and unlimited levels by using a nested UL and radiobuttons enjoy.

Update: the second demo now allows for preselect states and shows the first dropdown enjoy.

The interface element of connected select boxes (one select box changing the options in the other one) is one of the most used and also most annoying elements of web application design. While it works nicely for anyone having JavaScript enabled and using a mouse it can be a nightmare to use with a keyboard (unless you know that you can expand the whole list with alt+cursor down first).

The other problem is that you make yourself dependent on JavaScript with them and I don’t even want to know what the implementations for screen readers are.

That said, it simply does not die out, people love it. The scary thing is that there are dozens of JavaScript solutions to the problem and almost all of them make you dependent on JavaScript. I’ve tried in the past to come up with solutions for it using for example nested HTML lists in this Alistapart article. What scares me most is that the demo code for a bad solution seems to have ended up on several “Script Library” sites and I get emails coming in thanking me for the great solution!

My personal favourite is keeping the functionality independent of a mouse and JavaScript and using Ajax to populate the second drop down as explained in my book, but that is too complex for a lot of owners of web interfaces.

So today, once again the request for connected select boxes reared its ugly head and my esteemed colleague Bradley Wright took it onto himself to solve the issue (working with this guy does rock - believe me). His approach was to create a massive dropdown with all the information and then use JavaScript to chunk it up. Originally he tried class names on the different options to connect them until he asked me to take a peek and I liked the idea but advocated for optgroups instead (the lesser known select child element).

So, the markup for the non-JavaScript version is the following:


<select id="ori">
  <optgroup label="Foo1">
    <option value="foo1">Foo1</option>
    <option value="foo1_1">Foo1_1</option>
    <option value="foo1_2">Foo1_2</option>
    <option value="foo1_3">Foo1_3</option>
    <option value="foo1_4">Foo1_4</option>
    <option value="foo1_5">Foo1_5</option>
    <option value="foo1_6">Foo1_6</option>
  </optgroup> 
  <optgroup label="Foo2">
    <option value="Foo2">Foo2</option>
    <option value="Foo2_1">Foo2_1</option>
    <option value="Foo2_2">Foo2_2</option>
    <option value="Foo2_3">Foo2_3</option>
    <option value="Foo2_4">Foo2_4</option>
    <option value="Foo2_5">Foo2_5</option>
    <option value="Foo2_6">Foo2_6</option>
  </optgroup> 
  <optgroup label="Foo3">
    <option value="Foo3">Foo3</option>
    <option value="Foo3_1">Foo3_1</option>
    <option value="Foo3_2">Foo3_2</option>
    <option value="Foo3_3">Foo3_3</option>
    <option value="Foo3_4">Foo3_4</option>
    <option value="Foo3_5">Foo3_5</option>
    <option value="Foo3_6">Foo3_6</option>
  </optgroup> 
  <optgroup label="Foo4">
    <option value="Foo4">Foo4</option>
    <option value="Foo4_1">Foo4_1</option>
    <option value="Foo4_2">Foo4_2</option>
    <option value="Foo4_3">Foo4_3</option>
    <option value="Foo4_4">Foo4_4</option>
    <option value="Foo4_5">Foo4_5</option>
    <option value="Foo4_6">Foo4_6</option>
  </optgroup> 
</select>

All we need now to turn this into connected select boxes is the folllowing:

  • Create a new select element
  • Loop through all optgroups and create a new select box for each and hide them
  • Loop through the options collection of each optgroup
  • Take the first option and add it to the new main select element
  • Move the other options to the select box connected with this optgroup
  • Apply an onchange handler that reads the selectedIndex value of the main select element and shows the select box with the same number, hiding the previous one
  • Apply the correct secondary name to the currently shown select box
  • Remove the original select box
  • Apply the name and ID of the original to the new main select box

Another option is of course to store the data in an object and re-populate the secondary select box every time the first is changed. However, I wanted to avoid that to speed things up.

Check out the example of this technique and tell me what you think.

43 Responses to “Unobtrusive connected select boxes - yet another solution approach”

  1. Tom Says:

    It’s an excellent idea chaps. I wonder if it would be better to rewrite the original checkbox based on the optgroup labels rather than having a base element ‘Foo1′, ‘Foo2′, etc. It seems like you don’t actually want anyone to select those really.

    Why not have the first script created select box take the values of the labels on the optgroups and the second one display as is?

  2. mwarden Says:

    Very cool. We will use this technique in our current project.

  3. Dean Says:

    When I load the demo page I don’t see the second select list until I make a selection from the first one. (I’m using FF2 on Windows XP)

  4. Mike West Says:

    Christian: Nice work. `OPTGROUP` is simply perfect for this application… it’s a great example of distilling exactly what markup maps to the central problem that you’re trying to solve, and extending it into a hi-fi interface in an unobtrusive manner.

    Tom: Without that “FooX” option, users without JavaScript wouldn’t be able to replicate the experience of choosing an item from the initial dropdown box while leaving the second dropdown blank.

    That might or might not be preferable, depending on your needs. :)

  5. Ara Pehlivanian Says:

    That’s excellent, very elegant, I like it a lot. It’s too bad you can’t nest optgroups though, because it would have been the perfect solution!

  6. Max Schwanekamp Says:

    Pretty clever. I bet you know this already, but the keyboard navigation is a bit funky, though, at least in FF 2.0.0.2. Put focus on the first element, [tab], and my focus box jumps to the submit element, so I have to [shift]-[tab] to get the second select element. If, after the second element is already created, I tab back to the first one and change it and then my focus is gone, and [tab] again brings focus on the first select, again. Minor, and easily remedied.

    Ah, works as expected in IE6 & 7.

  7. Blog » Lesenswert Nr. 3 » Holzapfel & Bayer (Webdesign Neuss, Düsseldorf und Mönchengladbach) Says:

    [...] t Is Your Framework?« Jens Meiert: »(X)HTML 5 und XHTML 2 im Vergleich« Chris Heilmann: »Unobtrusive connected select boxes - yet another solution approach« »AskTheCSSGuy.com«: »Form fi [...]

  8. Francisco Artal Says:

    Thank you for helping us to do things better.

    I tried your code with JavaScript enabled, without it and, with JavaScript enabled and CSS disabled.
    The last one did not work as expected.

    I have just bought your book so is too soon for me to give my own solution.

  9. rich Says:

    In response to Tom’s comment, I needed an initial Select based on the Optgroup label as well, and managed to modify the second demo scripts code to do this.

    Its a matter of four additional lines of code in the main loop - it should be pretty obvious where these go if you view source on the seond demo and compare:


    splitSelect.selects.push(news);
    var k=0;
    /* Use optgroup labels for first select */
    var v = o[0].getAttribute(’value’); var l = g[i].getAttribute(’label’); o[0].setAttribute("value", v);
    o[0].innerHTML = l;
    /*End modification*/
    c.appendChild(o[0]);

    Hope this helps anyone else with the same aim.

  10. pauldwaite Says:

    Cool. But yeah, I guess it won’t work if you need more than one level of nesting, or if a top level should be selectable. Still cool though.

  11. Soren Says:

    This is an excellent idea, but I have a major problem with it: Without Javascript you can select “Foo2″, but with Javascript enabled you can’t.

    <optgroup label=”Foo2″>
    <option value=”Foo2″>Foo2</option>

    It appears it requires the first option after an optgroup to be the same as the optgroup label. The select box I have to try this technique on, my optgroups are section headings, and not meant to be selectable.

    Perhaps richs modification deals with this problem, but I can’t use it because it uses innerHTML(), which is not part of any standard DOM.

  12. Jerome Says:

    @Soren “I can’t use it because it uses innerHTML(), which is not part of any standard DOM.

    It might not be part of the W3C DOM spec but why does that matter in the real world where all significant browsers support it? If that’s some kind of company policy then I’d be looking for a job somewhere they don’t try to suffocate me with bizarre regulations.

  13. James Oppenheim Says:

    Really good idea. Previously to get around this I just reloaded the page with different GET variables. Nice work I will have to give it a try.

  14. links for 2007-04-19 » mhinze.com Says:

    [...] : SYSK 331: How To Expose A Client-Side Event From Your ASP.NET Control (tags: asp.net) Unobtrusive con [...]

  15. web Says:

    Nice.

    Semantics + Accessibility + Progressive Enhancement gets me all hot and bothered!

  16. All in a days work… Says:

    [...] t’s not just for games anymore - think Google Reader and Gmail) (tags: JavaScript) Unobtrusive connected select boxes - yet another solution approach His approach: create a massive drop [...]

  17. JP Says:

    The keyboard accessibility doesn’t work in Firefox on OSX. I haven’t had a chance to look at what might be the issue, but figured I’d mention it in case you didn’t have access to a mac.

  18. Soren Says:

    @Jerome “It might not be part of the W3C DOM spec but why does that matter in the real world where all significant browsers support it?”

    You are not thinking long-term. In 2002 I had to clean up a lot of javascript from 1997 that checked for the browser being IE4 or Netscape4, and assumed you had an old browser if it wasn’t one of these. That gave me a healthy dislike of anything non-standard.

    The thing is that webbrowsers parse HTML into a tree structure in memory. If you use the standard DOM API, you manipulate the tree directly, but if you use document.write() or innerHTML, you force the browser to reparse the document and rebuild the tree structure. This is slow.

    There is a standard called XHTML. It is HTML written as XML. It can be served as two content-types. Text/html or application/xhtml+xml. If you use the latter, Firefox will use the XML parser, that is much faster, but less tolerant of syntax errors. Faster is good, but it comes at the expense that document.write() et al are disabled. Why? Because they force the browser to treat the page as SGML.

    So, are you going to require of your employer that all their webpage in all future be served as text/html just because you like non-standard innerHTML?

  19. Natalie Downe » Blog Archive » links for 2007-04-20 Says:

    [...] i can sync my life aka my google calender to my desktop (tags: mac productivity google) Unobtrusive connected select boxes - yet another solution approach - Wait till I come! nicely implemen [...]

  20. links for 2007-04-21 « toonz Says:

    [...] ge - Download Squad (tags: Business usability web) Polar Clock (tags: clock flash Art) Unobtrusive connected select boxes - yet another solution approach - Wait till I come! (tags: javascri [...]

  21. Filter for 19/4 2007 - Felt Says:

    [...] – VÃ¥lerengasjappa!- Nice product, and lice launch, from a Norwegian company even! Wait till I come: Unobtrusive connected select boxes via HD BizBlog: Re-Thinking Your Workspace Link [...]

  22. RUDEWORKS » Archivo » Cajas de selección conectadas Says:

    [...] Cajas de selección conectadas 25 de Abril, 2007 a las 11:01 Conectar cajas de opciones fácilmente, mediante JavaScript. Archivado en: javascript m [...]

  23. DonnaM Says:

    Lovely solution and just in time for a project I’m working on.

    Now I just wish I was smart enough to abstract it so I can use it more than once on a page…

  24. Unobtrusive connected select boxes (Chris Heilmann) / Web Words / WizarDev Says:

    [...] an expand the whole list with alt+cursor down first). (Article dated: March 17, 2007) Read Unobtrusive connected select boxes [...]

  25. » Unobtrusive and keyboard accessible connected select boxes Says:

    [...] options do we have? One option that looks promising is described by Christian Heilmann in Unobtrusive connected select boxes - yet another solution approach. It involves using optgroup element [...]

  26. Best of April 2007 | Smashing Magazine Says:

    [...] basis and is protected against PHP header injection. CSS-Techniques, (X)HTML, PHP Unobtrusive connected select boxes The interface element of connected select boxes (one select box cha [...]

  27. Web-Design Blog » Blog Archive » Best of April 2007 Says:

    [...] basis and is protected against PHP header injection. CSS-Techniques, (X)HTML, PHP Unobtrusive connected select boxes The interface element of connected select boxes (one select box cha [...]

  28. Webdesign (css, grafica e altro) » Blog Archive » Best of April 2007 Says:

    [...] basis and is protected against PHP header injection. CSS-Techniques, (X)HTML, PHP Unobtrusive connected select boxes The interface element of connected select boxes (one select box cha [...]

  29. One Measly Dollar » Blog Archive » links for 2007-04-21 Says:

    [...] t Justified Nice further exploration of * {margin: 0; padding: 0;} (tags: css code tips) Unobtrusive connected select boxes - yet another solution approach - Wait till I come! How timely, I c [...]

  30. Tekjuice.com » Blog Archive » Best of April 2007 Says:

    [...] basis and is protected against PHP header injection. CSS-Techniques, (X)HTML, PHP Unobtrusive connected select boxes The interface element of connected select boxes (one select box cha [...]

  31. Web design purity « The Dumping Ground Says:

    [...] iscovered the benefits of keeping things nicely seperated. Chris Heilmann has an excellent example of a couple of list boxes that can be filtered that doesn’t break down if javascript is turn [...]

  32. Presseschau für Webentwickler - Ausgabe Juli 2007 | Dr. Web Weblog Says:

    [...] uot; Navigation
    Eine Technik zur Erzeugung eines Inhaltsverzeichnisses mit CSS.

    Unobtrusive connected select boxes - yet another solution approach - Wait till I come!
    DOM-Script-b [...]

  33. Best of May/June 2007 Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  34. Best of May/June 2007 | Webdesign (css, grafica e altro) Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  35. lost node » Blog Archive » Best of May/June 2007 Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  36. Best of May/June 2007 | Webdesign (css, grafica e altro) Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  37. Cyber Space in One Hand » Blog Archive » Useful references, tutorials, services, tools, techniques and articles by smashingmagazine Says:

    [...] n your site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script-b [...]

  38. Best of May/June 2007 · Style Grind Says:

    [...] te ready for even more styling.

    Unobtrusive connected select boxes - yet another solution approach - Wait till I come!
    A DOM-Script [...]

  39. Best of May/June 2007 | Webdesign (css, grafica e altro) Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  40. Best of May/June 2007 | Webdesign (css, grafica e altro) Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  41. Best of May/June 2007 at Design Resources Says:

    [...] site ready for even more styling. Unobtrusive connected select boxes - yet another solution approach - Wait till I come! A DOM-Script- [...]

  42. Christoph Taubmann Says:

    hi
    great job!
    i try to adapt Update#2 to use a href instead of input-fields. the first menu is parsed but i have some probs to get a proper unlimitedSelect.parents[n] in the dochange:function (tried to use random ids instead of values).
    chris

  43. deviantz Says:

    nice.. great job! this is a very useful article! keep it up! thanks!

Leave a Reply

Wait till I come! is the blog of , a developer evangelist living and working in London, England. Download vcard.

Feed me, Seymour: Entries (RSS) and Comments (RSS).