Checkbox inputs can only have two states: checked or unchecked. They can have any value, but they either submit that value (checked) or don’t (unchecked) with a form submission. The default is unchecked. You can control that in HTML like this:
<!-- Default to unchecked -->
<input type="checkbox">
<!-- Default to checked, XHTML -->
<input type="checkbox" checked="checked" />
<!-- Default to checked, HTML5 -->
<input type="checkbox" checked>
Visually, there are actually three states a checkbox can be in: checked, unchecked, or indeterminate. They look like this:
Here are some things to know about indeterminate checkboxes:
You can’t make a checkbox indeterminate through HTML. There is no indeterminate attribute. It is a property of checkboxes though, which you can change via JavaScript.
var checkbox = document.getElementById("some-checkbox");
checkbox.indeterminate = true;
or jQuery style:
$("#some-checkbox").prop("indeterminate", true); // prop is jQuery 1.6+
The indeterminate state is visual only. The checkbox is still either checked or unchecked as a state. That means the visual indeterminate state masks the real value of the checkbox, so that better make sense in your UI!
Like the checkboxes themselves, indeterminate state looks different in different browsers. Here’s Opera 11.50 on Mac:
Use Case
The reason I’m writing this is because I just had a use case come up for this state: nested checkboxes. Each checkbox may have child checkboxes. If all those children are checked, it may be checked. If none are checked, it is unchecked. If some of them are checked, then it’s in an indeterminate state (in this case symbolically meaning “partially” checked).
Here’s that in jQuery:
See the Pen Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.
Here’s an alternate jQuery version from TheNotary.
And here’s a plain JavaScript version from Jakob Eriksen:
See the Pen
Indeterminate Checkboxes (Vanilla JS) by jakob-e (@jakob-e)
on CodePen.
And a couple of alternate approachs from Alvaro Montoro , Bramus, Gridbuilder, Lewin Probst, and Jason Wilson.
Using StimulusJS from Stephen Margheim:
See the Pen
checkbox family by Stephen Margheim (@smargh)
on CodePen.
Rotating amongst the states
Jon Stuebe was messing around with the idea of rotating the state between unchecked, indeterminate, and checked with a click. Here’s some jQuery to do that:
var $check = $("input[type=checkbox]"), el;
$check
.data('checked',0)
.click(function(e) {
el = $(this);
switch(el.data('checked')) {
// unchecked, going indeterminate
case 0:
el.data('checked',1);
el.prop('indeterminate',true);
break;
// indeterminate, going checked
case 1:
el.data('checked',2);
el.prop('indeterminate',false);
el.prop('checked',true);
break;
// checked, going unchecked
default:
el.data('checked',0);
el.prop('indeterminate',false);
el.prop('checked',false);
}
});
See the Pen Rotate Through Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.
Reader Casual Trash sent me in a library-free and far more succinct version of rotating through all three visual states which utilizes the readonly
attribute that checkbox inputs can have.
<!-- Inline click handler, just for demo -->
<input type="checkbox" id="cb1" onclick="ts(this)">
function ts(cb) {
if (cb.readOnly) cb.checked=cb.readOnly=false;
else if (!cb.checked) cb.readOnly=cb.indeterminate=true;
}
See the Pen Rotate Through Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.
Thanks,
Just tried to find how to implement it some days ago.
Have decided to make like in Gmail: opacity: .5;
Now thinking of rewriting the code.
Thanks for sharing this, I never knew :)
You open up saying checkboxes only have two values. However, checkboxes have the attribute ‘value’ as well. Did you mean something like ‘state’?
http://w3schools.com/html5/att_input_value.asp
I agree… small mistake by Chris, I am sure he did it in hurry.
However, great lesson.
whats the browser support for this?
I did a little testing and i found it works as far back as IE 6
PS: Nice tutorial Chris, i saw this somewhere recently not as detailed as this.
Out of curiosity: what value would an indeterminate checkbox return in this example?
The indeterminate attribute is not related to check/unchecked or the value attribute. In indeterminate, checked checkbox with value 42 would return 42, an indeterminate, unchecked checkbox with value 37 would return nothing.
I don’t think Chrome allow us to do it :/
Works fine for me in Chrome
Yes, really doesn’t work in Chrome.
It works fine for me? Do you have the latest version of Chrome?
Of course :) Chrome version – 13.0.782.112 m (for Windows)
The reason checkboxes look so ugly in Opera in your demo is this CSS rule:
If you try to style checkboxes (and radios as well) in Opera, they will get that ugly “Windows 98” look.
Whydid you use .prop() instead of .attr() ?
I’m not an expert in this area —
.prop()
is new to me — but here’s what the documentation says:Didn’t knew this.
Thanks a lot for sharing.
Wow, that’s crazy! I had no idea browsers supported this at all.
Thanks!
hi chris,
i don’t know if is that normal
first check “giants” than uncheck “andre” and “paul bunyan” than see what happens
See last sentence.
Well, I see a lot of logic in this… If none of the childrens are selected then it should be no reason for the parent to be checked.
It’s a very logic limitation….
Been using checkboxes and other form elements for over 10 years, but I guess you learn something new everyday!
The best use case I have seen for this is in the git-tower app. They use the indeterminate checkbox when you have only part of a file staged.
Here is a screenshot showing it:
http://bit.ly/ornzBG
Thanks! Learn something new every day!
You learn something new… sometimes.
excellent, was not aware of this trick,
My Javascript/jQuery knowledge is supremely limited, but I wanted to take a shot at making changes recursive. There’s still problems with it. Someone else could probably make it way better.
I keep thinking about another way:
-event Delegation with jQuery:
$(‘ul’).delegate(‘li’, ‘click’, function(event) {
// this == li element
});
-a multidimensional array keeping track of all the <li>s current states, default/start all columns and rows 0, changed on click
in order to provide a mechanism to add or remove the indeterminate class name to all li that need it.
I’ll see if I can put together some code tomorrow.
Oh my god! I didn’t even know this was possible! Great :D
Chris,
The label for “Short Things” seems wrong:
<label for="tall">Short Things</label>
Shouldn’t it be
<label for="short">...
?Anyway.. clicking on the text “Short Things” activates the “Tall Things” checkbox.
It’s just a typo :)
if you change it to ‘short’ (obviously in the second instance) it works as expected; that is, it selects all the Short Things’.
fixed.
Here’s my attempt:
http://jsfiddle.net/davishmcclurg/fzELD/
Doesn’t seem to work on my nexus one running android.
Great article and an awesome new design to the site, Chris! Really great design.
New site looks good, not a fan on the buttons and the rainbow hover though
Beautiful new design!
I wonder if there’s any way of retrieving that indeterminate status after a form submit.
This could come in handy when interpreting some kind of survey to determine if the checkbox was clicked at all (set to true or false) or it was completely ignored, and thus not even clicked once.
Chris, do you have any information on this one?
I bet there would be a gain in value for wufoo in this, too. ;)
Since you have to set it with JS, you’d have to alter the actual value of the checkbox somehow. So like value = value + “-indeterminate”.
Yeps,
I guess a workaround would do the job since you’re using JS for the fiddling already.
Maybe HTML6 will do it. ;)
Thanks for the quick response!
Boolean input fields with more than 2 states?
This is almost as bad as dividing by zero!
It works fine in firefox and ie but i am having issues with chrome.Is any quick fix available?
looks great, the only thing I noticed is if you click on an indeterminate checkbox it loses its “green” fill/state, which I don’t think is a desired behavior?
Hello,
I’d like to find the same thing, but with a “init” function. Than, if some checkboxes are “pre”-checked (pre-populate form ie) => it determines the states of the parents boxes before any changes, with low level to high level priority.
Any ideas ?
Thanks a lots !!!
Fixed a bug related to improper installation attribute indeterminate and optimized code. Now it has a smaller volume and removed the useless cycles.
how to achieve for the simple Html.
<input type="checkbox" value="something" indeterminate/>
this won’t work
<input type="checkbox" value="something" indeterminate="true"/>
either this one
<input type="checkbox" value="something" indeterminate="indeterminate"/>
What is the way to make it work.
The code is failing in one scenario for my code not sure why……
http://jsfiddle.net/sameerengg/84ajt/6/
please help.
Found the problem ul was extra removed that working fine now……
There is one more problem which I found on IE where we have intermediate checked
when you change that the change event is not fired. I changed it to click event and it is working for me.