Usable multiple-selection with checkbox lists and jQuery

There are two out-of-the-box methods for multiple selection in HTML: checkboxes and the <select> tag. Neither are perfect - I’ll be discussing why, and proposing a sort of mashup of the best aspects of both, using jQuery.

The vanilla HTML implementations of these two methods are shown below:

1) Select tag:

(Hold ctrl or command to select multiple values)

2) Checkboxes and Label tag:

Note that the <label> tag allows users to click the label to toggle the checkbox on and off.

In terms of usability,  the checkbox method is more straightforward - it is obvious how to select multiple values, whereas with the select method we have to tell the user which keys to hold down. In addition to that, if a user has selected multiple items, and then forgets to hold the correct key on the next click, their selection is lost and only the last value clicked is selected. On a list that can be scrolled, it may not even be apparent that the other selections have been lost.

The disadvantages of the checkbox method are:

  • It’s not obvious that the label can be clicked.
  • It would be nice if a larger area were clickable, as with the SELECT example
  • It would be nice if the entire row were highlighted, as with the SELECT example
  • The values are not scrollable - adding more will simply show a longer list

We’re going to fix all that with some simple CSS and Javascript (using JQuery).

Click to see an example page

Edit 1 - 9/4/09: Simplify code as per Victor’s comments, and fix refresh issue in Firefox

Edit 2 - 9/4/09: Simplified again, using just the label tags, without <a> tags, from the reddit comments


	$(document).ready(function() {

		// make sure labels are drawn in the correct state

		$('label').each(function()
		{

			if ($(this).find(':checkbox').attr('checked'))
				$(this).addClass('selected');

		});

		// toggle label css when checkbox is clicked

		$(':checkbox').click(function(e)
		{

			var checked = $(this).attr('checked');
			$(this).closest('label').toggleClass('selected', checked);

		});

	});