the 16 states of a checkbox

Yes, thats right, there are 16 possible states a checkbox can have! gotta catch 'em all!

1. no state

Ok, so this one is a bit of a cheat, I'm counting one state when the checkbox isn't in :hover, :focus, :active or :checked. boo.

2. :hover

So lets start with a simple one. hover is only when the cursor is hovering over a checkbox that isn't in focus and hasn't been checked. thats it.

3. :focus

All inputs can have :focus. It's more obvious when a text input or textarea is in focus because there is usually a blinking cursor in the area where you're about to type. This lets you move your cursor away, whilst remaining in "focus". An input will lose focus when you click, or "tab" somewhere else.

focus is kinda like a way of communicating to the user that "hey, if you press spacebar or type a letter, this is the element that will be affected"

4. :active

the :active state is when you are "in the processes" of checking or unchecking the box, by means of either clicking the mouse or some keyboard interaction (usually by pressing spacebar). Basically that split second between pressing and releasing.

to get the :active state by itself is actually not that common, since you have to click (hold down the mouse button) and simultaneously move the mouse away from the checkbox, so that it's no longer hovering over it.

fun fact: when you mouse click (hold the mouse down) on a checkbox it will become active, but lose focus. But when you press (hold down) spacebar, the element will not lose focus... go figure.

5. :checked

This is when the checkbox has a tick in it.

The :checked state is only applied after the mouse or spacebar has been released.

6. :hover:focus

hover and focus. This is when the cursor is hovering over a checkbox that happens to be in focus. The two actually have nothing to do with each other, you can be hovering over the checkbox whilst another form element is in focus, and vice-versa.

7. :hover:active

As previously mentioned, using the mouse to click a checkbox will add the active state, but remove the focus state, the focus state is added again after you release the mouse. To get both hover and active you simply hold down the mouse on an unchecked checkbox.

8. :hover:checked

Simple. Hover over an unfocused checked checkbox.

9. :focus:active

Hold the spacebar on an unchecked checkbox, whilst the cursor is elsewhere.

10. :focus:checked

Same as number 3, except the checkbox is already checked.

11. :active:checked

This is a tricky one to get. Just like number 4 you have to hold down the mouse and move the cursor away from the checkbox. The only difference is that the checkbox has to be checked before you click on it.

12. :hover:focus:active

For this one you need to hold the spacebar on an unchecked checkbox, whilst the cursor is hovering over it.

13. :hover:focus:checked

Simply hovering over a focused checkbox, that is checked.

14. :hover:active:checked

Press and hold the mouse on an already checked checkbox. After you release the mouse focus will come back and active and checked will go.

15. :focus:active:checked

Press and hold the spacebar on an already checked checkbox, with the cursor somewhere else.

16. :hover:focus:active:checked

Bingo! To get all 4 the cursor has to be hovering over an already checked checkbox that is in focus, then hold down the spacebar. At this point you will add the :active state, but the :checked state will not be removed yet (this happens after you release the spacebar) You can't hold down the mouse to get all 4 states, since pressing the mouse removes the :focus state.

Sooo, should I account for all 16 states in my css?

Erm, not really, no.

If you are customizing your checkboxes, by hiding the browser default one, then your html might look something like this...

    <input type="checkbox" name="name">
    <span class="checkbox"></span>
    <span class="label">Click me!</span>

and something like the following state css would be enough (along with all the regular checkbox styling)

/* empty box */                
label .checkbox {
    background-image: url("/images/check_box.svg");

/* same style for focus and active */
label :focus + .checkbox,
label :active + .checkbox {
    border: 2px solid rgba(0,0,255,0.3);   /* or... */
    outline: 3px solid rgba(0,0,255,0.3);  /* or maybe even... */
    background-color: rgba(0,0,255,0.3);

/* checkbox checked */
label :checked + .checkbox {
    background-image: url("/images/check_box_checked.svg");

Note: If you are hiding the original input checkbox, dont just use display:none; as this will make it unfocusable. Instead hide it visually like so

[type=checkbox] {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
    white-space: nowrap;