Skip to main content

Posts

Check it, don't select it

By Nicholas Rougeux, posted on December 17, 2005 in CSS, Web

Usability and accessibility are all the rage right now and that's great because it's slowly making the web a better place. Unfortunately, some of the goodies in our bags of tricks aren't quite up to snuff when it comes to these two areas. One such goody is the good old select element—specifically with the multiple attribute enabled. How about we do away with them and try something different?

The biggest problem with multiple-select boxes is that selecting multiple options is a pain, especially if there are enough to create a scrollbar within the box. The most common place I've seen this scenario is in content management systems. For example, let's say you are writing an article for a site in a CMS and want it to appear in several categories on the front end of a site. (Let's assume that the system is not using tags for this example.) To related it to these categories, a multiple-select box is usually shown with all the categories of the site as options. You would have to hold down Ctrl and select each category. This may include scrolling within the box and if you love using the handy dandy scroll wheel on mice, then you may click in the box again to enable focus and start scrolling down—but wait! You just clicked without holding Ctrl so you just deselected all the previously-selected options. Now you have to go back and remember what you picked and use the scroll bar to scroll down. Sure, you set focus to the element by selecting the elements with Ctrl but not everyone knows that. All this backing and forthing gets to be a real pain.

Why not replace that cumbersome select box with a scrollable checklist? Recently, I was working in Visual Studio and noticed a control called CheckedListBox (who names these things?) and thought I would try to make one for use on the web using some standard elements and a smattering of CSS. Follow along below to see how I did it, see the final basic result or check out some fancy examples.

The first step is to create the structure. I did this by simply using an unordered list, some labels, and checkboxes:

<form action="#" method="get">
    <ul class="checklist">
        <li><label for="o1"><input id="o1" name="o1" type="checkbox" /> Aenean malesuada ante eget tellus</label></li>
        <li><label for="o2"><input id="o2" name="o2" type="checkbox" /> In posuere augue id velit</label></li>
        <li><label for="o3"><input id="o3" name="o3" type="checkbox" /> Nullam a dui ac augue adipiscing sodales</label></li>
        <li><label for="o4"><input id="o4" name="o4" type="checkbox" /> Vivamus consectetuer ante eget urna</label></li>
        <li><label for="o5"><input id="o5" name="o5" type="checkbox" /> Aliquam id felis cursus purus tristique condimentum</label></li>
        <li><label for="o6"><input id="o6" name="o6" type="checkbox" /> Suspendisse posuere lectus vitae velit consequat volutpat</label></li>
        <li><label for="o7"><input id="o7" name="o7" type="checkbox" /> Fusce condimentum nulla et tortor.</label></li>
        <li><label for="o8"><input id="o8" name="o8" type="checkbox" /> Proin consequat faucibus mi</label></li>
        <li><label for="o9"><input id="o9" name="o9" type="checkbox" /> Etiam a lectus quis massa viverra laoreet</label></li>
        <li><label for="o10"><input id="o10" name="o10" type="checkbox" /> Pellentesque gravida lorem vel odio</label></li>
    </ul>
</form>

That class on the unordered list is all we need to make the checklist. What we're going to do is so basic that it can be applied in many areas but I'm just using it for checklists for now. Next, we add a dab of CSS:

.checklist {
    border: 1px solid #ccc;
    list-style: none;
    height: 20em;
    overflow: auto;
    width: 16em;
}

.checklist, .checklist li { margin: 0; padding: 0; }

.checklist label {
    display: block;
    padding-left: 25px;
    text-indent: -25px;
}

.checklist label:hover { background: #777; color: #fff; }

Now we have very basic scrollable checklists without all the hassle of worrying about deselecting previously-selected options. Setting overflow: auto is what creates the scrollable area and with the height and width units set as ems, the entire thing is resizable. We also style the labels to have a block display to make the entire option clickable and add some padding but set a negative text indent so the words can wrap to the next line without appearing underneath the checkboxes. One extra helpful style was added to labels when hovering over them to let users know that they can click on them.

Make IE play nice

We're done, right? Nope. As usual in the world of CSS, Internet Explorer rears it's bothersome head and imposes some unwanted limits. Unfortunately, setting the labels' display property to "block" brings about the infamous white space bug in which IE displays the white space in between the li tags. To solve this, use the Holly hack and add a height declaration to the label properties:

.checklist label {
    display: block;
    height: 1%;
    padding-left: 25px;
    text-indent: -25px;
}

The final thing we need to do for IE is to implement a version of the JavaScript introduced in A List Apart's Suckerfish Dropdowns. This JavaScript allows IE to change the background of the labels just like modern browsers do with the :hover pseudoclass:

function initChecklist() {
    if (document.all && document.getElementById) {
        // Get all unordered lists
	   var lists = document.getElementsByTagName("ul");
        
        for (i = 0; i < lists.length; i++) {
            var theList = lists[i];
            
		  // Only work with those having the class "checklist"
            if (theList.className.indexOf("checklist") > -1) {
                var labels = theList.getElementsByTagName("label");
                
			 // Assign event handlers to labels within
                for (var j = 0; j < labels.length; j++) {
                    var theLabel = labels[j];
                    theLabel.onmouseover = function() { this.className += " hover"; };
                    theLabel.onmouseout = function() { this.className = this.className.replace(" hover", ""); };
                }
            }
        }
    }
}

Load this function when the page loads using Simon Willison's addLoadEvent and you're good to go.

Now you're free to style your checklists however you like and you have much more freedom in doing so than trying to style select boxes. Check out the final result or take a look at some possibilities.

I'm no expert, so if I've made a mistake somewhere or things can be streamlined a bit more, please don't hesitate to offer up suggestions.

Update: Internet Explorer 7 is known to display the scrollable checklists improperly. This is due to the fix applied to make Internet Explorer play nice as mentioned above. Fortunately, the fix is simple. Just remove the height: 1%; declaration and put it on its own line and target IE versions 6 and below:

.checklist label {
    display: block;
    padding-left: 25px;
    text-indent: -25px;
}

* html .checklist label { height: 1%; }

The targeting is done by making use of the popular star hack.

The samples have been updated with the adjustment.

Translations

This article has been translated into the following language:


Comments

  1. 1 Thibaut

    Posted on December 17, 2005

    Very nice. Thank you for sharing this.

  2. 2 Brian Benzinger

    Posted on December 18, 2005

    I love it. Excellent article. I'm definitely going to put this into use one of these days. I'll be sure to let you know if I do. Great work!

  3. 3 Amit Snyderman

    Posted on December 18, 2005

    A nice extension of this would be to assign a click-handler to the labels so that clicking the whole label toggles the checkbox; especially since you're changing the background color, it makes the label feel like a big button just waiting for a click. Great idea.

  4. 4 Joshua

    Posted on December 18, 2005

    Good innovation!

  5. 5 Teddy Zetterlund

    Posted on December 19, 2005

    Excellent article, I might actually use this in my upcoming project - really nice timeing. But if someone is using select lists the way you described in this article then I think that's a misstake by them. To get the same result as these checklist with select lists - this is how to do it properly (not more beautyful though, hehe): http://www.cs.helsinki.fi/u/salaakso/patterns/Double-List.html

  6. 6 Freddy

    Posted on December 19, 2005

    I do really like this one! You really hit the nail on the head with that one, because I always get so annoyed when you have to scroll down the select item, even if it's not one of those so called 'multiple' thingiemejiggs.

    I also like that :hover - Javascript for IE (I know it's not your idea, but I still think it's a good one!)

    But now, je ne suis pas une experte with Javascript, but while comparing the two 'for()' loops, I saw the following:

    for (i = 0; i < lists.length; i++) {
    theList = lists[i];
    for (var j = 0; j < labels.length; j++) {
    var theLabel = labels[j];

    Doesn't 'theList' need to be a variable too? (might not have to, haven't tested it or anything.

    Cheers,
    Freddy

  7. 7 Heiko

    Posted on December 19, 2005

    Very nice tutorial and compliment for the scrollable checklists!

  8. 8 Nicholas Rougeux

    Posted on December 19, 2005

    Amit, most browsers support the clicking of a label to set focus to an input element so there's no need to use an onclick handler. I know Safari doesn't support it but it's simple to build an event handler that does that.

    Freddy, thanks for pointing that out. I've updated the code. :)

  9. 9 Patrick Ohearn

    Posted on December 19, 2005

    Very nice hack for IE there :).
    It dosnt look right in Firefox on Linux, the fake iframe seems to go over 1px to far.

    Email me if you want a screenshot

  10. 10 Johan

    Posted on December 19, 2005

    This is nice. What would be nicer is to make the entire text clickable (text right of select box marks select box aswell). Makes more sense imo.

  11. 11 Marko

    Posted on December 19, 2005

    This really looks little odd, but I like it. It's different and definetly interesting

  12. 12 Chuck Reynolds

    Posted on December 19, 2005

    Hey cool - that could help with some of those backend module selectors that can, at times, get nightmarishly long...

    I like it - Good Job!

  13. 13 Sergei

    Posted on December 19, 2005

    Good job

  14. 14 Chris

    Posted on December 19, 2005

    This looks a LOT like http://verens.com/archives/2005/04/27/son-of-multiselect/ by Kae posted back in March and April. I've used Kae's code and added a sublevel so that in a large list, items can be grouped into parent categories. It's a little messy, but if anyone would like a copy, let me know and maybe i'll put a little more time into it and release it.

  15. 15 Jeremy

    Posted on December 19, 2005

    This also works fine for me in Opera 8.5 on OS X 10.4.

  16. 16 Zajako

    Posted on December 19, 2005

    Awesome idea, can also be used with radio buttons to replacea drop down menu allowing you to let them choose images.

    I like it :)

  17. 17 A Nony Mouse

    Posted on December 19, 2005

    Doesn't completely work on Opera 9 on Linux. When scrolling to the bottom, the mouseover forces it to scroll up slightly so you can't click on the bottom entry. Other than that, very slick!

  18. 18 Mark

    Posted on December 19, 2005

    If you're talking about "Usability and accessibility," you probably should realize you are making "select" elements less usable and less accessable by doing away with the shift-click functionality of a common select box. With shift-click functionality added, this would be a nice alternative to the select box, but as it stands right now, all you seem to be doing is taking away functionality.

  19. 19 David Moore

    Posted on December 19, 2005

    This may seem like a silly question - when this form passes the data on to the next form, what "name" should I be looking to pull if I am using a POST Form?

  20. 20 Peter Mescalchin

    Posted on December 19, 2005

    Excellent example. As Zajako above mentioned, using this with image/thumbnail selections would make for some nice UI.

    Dave to answer your question you need to query each checkbox option in turn (o1, o2, o3, etc. in Nicholas's example page). Alternately you can name all your checkboxes the same name with different values. You will then get the options back in a comma-delimited list which you can then split up and process in PHP/etc. quite easily.

  21. 21 Nicholas Rougeux

    Posted on December 19, 2005

    Chris (#14): Yes, it does look quite a lot like Kae's example. I hardly expected to be the first one to come up with it and I like the nice compact style Kae creates. Thanks for posting a link to it. She takes a different tack and I think her code could be cleaned up a tad but it's still a nice solution.

    Zajako (#17): I've seen it done that way and it works nicely. The only drawback to that is that if the list of images is long-ish, the load time becomes affected and displaying all of them when clicked can drag a bit.

    A Nony Mouse (#18): Thanks for letting me know about that bug. I don't have a Linux machine to test this stuff on so to hear that it mostly works is good news.

    Mark (#18): You raise a very valid point. My example is far from perfect. It's certainly possible to add the shift-click functionality with a little more work. While it may seem like I'm taking away some functionality, I'm adding more precaution against accidental deselection that often occurs. Plus—and this is a minor plus—it's surprising how many people don't know that you can hold down shift or control to select multiple options.

  22. 22 Ernesto

    Posted on December 19, 2005

    Not just in Opera 8.5 OSX, as Jeremy pointed out in #13 above. I can confirm that works for me in Opera 8.51 for Windows and Opera 8.51 for Linux.

    By the way, thanks for sharing this.

  23. 23 Nick Campbeln

    Posted on December 19, 2005

    Thank you so very much for this example! This is a VERY useful control that I'll be implementing into my own .Net web presentation layer (that's right kiddies, just cause you're developing with M$ doesn't mean your sites can't be cross-platform!).

    Thanks again! You'll be in my (eventual) props section for this control!

  24. 24 Greg Benedict

    Posted on December 20, 2005

    This is great. The only thing I would add would be to keep the checked items highlighted with the hover color (or another color like the default blue). This makes the selection choice much more obvious and shouldn't be hard to do.

  25. 25 Tim Pease

    Posted on December 20, 2005

    Let's try this again…

    To avoid using the "Holly Hack" to prevent IE from displaying the whitespace between list elements, you could write out the list in the following manner:

    <ul
    ><li>blah blah blah</li
    ><li>blah blah blah</li
    ></ul>

    The markup is still valid XHTML/HTML, but it removes any whitespace between list elements.

  26. 26 Brian Moeskau

    Posted on December 20, 2005

    Thanks. This is exactly what I was planning on writing myself at some point -- you have saved me some time!

    Regarding losing the shift-click functionality, I think it would be a nice added bonus if that was supported, but I also think that the usefulness of shift-click sort of depends on context. Personally, I usually don't find much need for 'bulk' list operations, but do frequently have long lists of items out of which only one or two items are typically selected. In these cases, I really do want checkboxes for the easier and more explicit interaction they offer, but also don't want to waste real estate. Perfect! [I also agree that most non-techies have no clue that shift/ctl-click even exist.]

  27. 27 Nicholas Rougeux

    Posted on December 20, 2005

    Tim (#25): Yes, that's certainly a viable solution but I've never been a fan of that becuase it makes editing the HTML a little odd and it could be prone to typos due to the unusual formatting. I guess it all comes down to personal preference. Sorry for the issues you had with posting. My system isn't perfect and I'm working on a fix.

  28. 28 Sebastian

    Posted on April 7, 2006

    We would be making something incorrect. In addition that would happen if this type of pages we would show them in another media like webtv or cell phone . In addition, the javscript is excessively greater when using and all that definition. To separate the logic of the presentation is a thing, but to use the presentation for everything is wrong. The select that allows many selections in the traditional way is ok and follows by on all the things being "accessible" as in this article say. This way unless is much expensive.

    ANd... sorry for my bad english

  29. 29 Anil

    Posted on December 30, 2007

    Anyone get this to work on Opera Mini 4 (for mobile devices)?
    Thanks.

  30. 30 Matt

    Posted on January 23, 2008

    hi there,
    how did you get the checkboxlist to display as ul? i get SPANs and INPUTS etc...which breaks the style

  31. 31 rajeev

    Posted on April 23, 2008

    Gr8

  32. 32 Eric

    Posted on April 28, 2008

    Thank you for the post! going to learn alot from it ;)

  33. 33 Rubens

    Posted on July 6, 2008

    Very nice Nicholas.

    Is there a way to make it so that the background changes colors for those labels that are checked?

    Thanks

  34. 34 Mike M

    Posted on September 17, 2008

    .ck8{background:red;}

    In document.ready

    $(":checkbox").click(function () {
    if($(this).is(":checked"))
    {
    //change background for the checkbox and the LI
    $(this).addClass("ck8").parent().addClass("ck8")
    }
    else
    {
    //reset the background for the checkbox and the LI
    $(this).removeClass("ck8").parent().removeClass("ck8")
    }
    });

  35. 35 Mike M

    Posted on September 17, 2008

    Oops, forgot to say that I didn't use the "label for" part of your original code so "parent()" for my code retrieves the LI's rather than the labels (don't ask, just weird in Lotus Notes with the labels!!!!) which i think will be the parents of the original code (maybe.parent().parent().addClass will work??)
  36. 36 Steve

    Posted on December 12, 2008

    Check out this for those guys that want to keep their multiple select boxes and have the extra functionality

    http://www.scotthorlbeck.com/code/tochecklist/

  37. 37 Iain

    Posted on August 5, 2009

    Perfect, Nicholas! Thanks for posting.

  38. 38 Evert

    Posted on October 5, 2009

    Thanks, for sharing this information. I am working on an inhouse form and was looking for other possibilities for multiple selection. I want to propose to use this type of multiple selection.

  39. 39 Natasha Nunn

    Posted on November 25, 2009

    Great idea! Very useful. I'll be using this for sure.

  40. 40 tony

    Posted on December 6, 2009

    Pon el zip que para mi tomar los codigos y emplearlos es fundamental,
    me he esforzado con css, pero tengo prioridades con otros lenguajes, te agradeceria me enviaras algunos codes a mi mail, cinceramente admiro su trabajo felicidades por la calidad y
    disculpen mi espaƱol por que no se ingles pero es bello esto de la web

  41. 41 anuncios

    Posted on February 22, 2010

    Thanx for the post ;)

  42. 42 mbt shoes

    Posted on March 31, 2010

    By now, the MBT shoes is the best online shop with good reputation, all cheap MBT shoes at wholesale price. MBT shoesis the first physiological footwear that has a positive effect on the whole body. It is really a good chance for shopping.

  43. 43 Jenny

    Posted on July 14, 2010

    I have used it in one of my project and I like this idea to much..

  44. 44 Ronaldo

    Posted on October 19, 2010

    muito bom

  45. 45 Leandro

    Posted on June 7, 2011

    This is nice, and it is what I was looking for.

    How can I output the list at first
    with some of the options already checked?

  46. 46 Leandro

    Posted on June 7, 2011

    This is nice, and it is what I was looking for.

    How can I output the list at first
    with some of the options already checked?

  47. 47 Leandro

    Posted on June 7, 2011

    Ok, just found out. Just add checked=yes to the input field.

  48. 48 Leandro

    Posted on June 7, 2011

    I mean, just add "checked" to the input field.

  49. 49 hoang nam

    Posted on November 8, 2011

    hoang van nam


Related posts

Stay in touch

Subscribe for updates

Get notified when new projects are released. Your email will not be sold or given to anyone else.