Tuesday, April 26, 2011

Tri-state checkbox with CSS

[update: see this new post from the always helpful Chris Coyier.]

There is no good way to represent a tri-state checkbox in HTML.
I’ve been googling and hacking around today on this topic. We can at best approximate the tri-state checkbox in HTML, and the methods I’ve found have their pros and cons. I will offer a pure CSS method, which too has its pros and cons. All require some javascript in order to function.

Method 1: Use Images

Here are two examples that simply use images to represent the various states of the checkbox:
  http://shamsmi.blogspot.com/2008/12/tri-state-checkbox-using-javascript.html
  http://plugins.jquery.com/project/tristate-checkbox
Pro
Con
You can count on these checkboxes always looking the same, no matter the browser, and no matter the version or the browser. It’s going to work and be consistent.

The jquery tristate-checkbox is available for use with jQuery, which has mainstream use.
You give up the native look and feel of the checkbox. This is even more apparent when the images are on a page along side native checkboxes.

You also give up the nuanced “hover” behaviors of an actual native control. To get this right, the following states should be accounted for:
  no-hover, unchecked
  no-hover, mixed 
  no-hover, checked
  hover, unchecked
  hover, mixed 
  hover, checked
  clicked, unchecked
  clicked, mixed 
  clicked, checked
  disabled, unchecked
  disabled, mixed 
  disabled, checked

Method 2: Use Opacity

In this suggestion, Pau Moreno offers to dial down the opacity (like gmail does somewhere?) to represent the “mixed” state.
  http://stackoverflow.com/questions/1726096/tri-state-check-box-in-html/4724216#4724216
Pro
Con
You get a purely native checkbox no matter what browser you use, as long as opacity is supported. (Opacity support does go back pretty far, which surprised me. Here’s an example of cross browser opacity css.) A “dimmed” checkbox does not convey the meaning of “mixed” state very well.

Method 3: Use CSS

This is my suggestion, which uses only native HTML checkbox and CSS. Here is a prototype with some hardcoded jQuery.
  http://www.gentomi.com/tri-state-checkbox.html
Here’s what it looks like on XP. (From left to right: Chrome, Firefox, Safari, IE8)
tri-state-checkbox-on-XP
You’ll have to look at the sources and stylesheets. Basically the input tag is followed with a couple of inline div tags which use the CSS relative/absolute position attributes to position a 7x7 green div square atop the checkbox to its left. It is just CSS. The javascript has to interpret the click event on the 7x7 square and “click” the checkbox.
Pro
Con
You get a purely native checkbox no matter what browser you use.

It is just CSS, so you can modify the “square” that represents the “mixed” state.
The CSS to position the square is browser dependent. This demo works in Chrome, FF, Safari, and IE7+. However, conditional stylesheets had to be made for IE.

I don’t have a Mac, or X-windows based browser, but I suspect the native checkboxes onthose platforms could be a pixel off in one direction or another from the overlying square. (Give me feedback…)

The overlying square masks the hover event from the native checkbox, so you lose that UI visual nuance when your mouse is over the square.


I’d like to hear some feedback from you, specifically if you see inconsistencies in the demo on other browsers/platforms.

Update 27 APR 2011

First, for the image-based solutions, I found another implementation (by Ryan Morlok) that covers the 12 cases I wanted.  http://softwareblog.morlok.net/2010/06/20/tri-state-checkbox/
Second, a friend sent me a screenshot of the CSS proof of concept rendered on a Mac. (From left to right: Chrome, Firefox, and Safari)
tri-state-checkbox-on-mac2
Clearly, separate CSS styles would need to be maintained for multiple platforms, in addition to multiple browsers.
Also, some googling revealed to me that to Mac users, a native tri-state checkbox is rendered with a “dash” rather than a “square”. This is possible to emulate since it is just CSS. Instead of a green 7x7 square, it would be a black 6x2 rectangle.
I also tried loading the proof of concept page on browsershots.org and found many of the unix platforms render the square in the wrong place as well. I’m not surprised.
I’d say this is a big issue for the “Cons” column. The number of platforms and browsers are large, but finite, and you could design the code to minimize the pain of adding new platform/browser offset information. But actually doing the legwork to maintain these nuances is very difficult; even with testing platforms like browsershots.org (and its contemporaries) getting this “just right” is still difficult. But if someone did maintain it, then I think I would really like this solution.
Meanwhile, I’ll vote for any future HTML standards that include a tri-state checkbox.