← Blog color-css

One CSS property choice decides whether keyboard users can check your custom checkbox at all

Scan to open this page

One CSS property choice decides whether keyboard users can check your custom checkbox at all

Before building Checkbox Style Generator, we ran a small, direct test on the two most common ways developers hide a native checkbox to replace it with a custom-styled one.

We called .focus() on both. Only one worked.

We created two checkboxes: one hidden with display: none, one hidden with opacity: 0 (plus positioning to keep it out of the visual flow). Calling .focus() on the display:none checkbox did nothing — document.activeElement never changed. The opacity:0 checkbox focused normally. That's not a subtle difference: it's the difference between a keyboard user being able to reach your custom checkbox at all, or not.

Why this keeps happening

display:none feels like the obvious way to "hide" something — it's the first property most people reach for. But it removes the element from the accessibility tree and the tab order entirely, which is exactly why multiple independent accessibility write-ups (from design-system teams to dedicated a11y guides) call this out as one of the most common custom-checkbox mistakes. This tool's generated CSS always uses opacity:0 instead, so that mistake isn't something you have to remember to avoid.

Focus rings and indeterminate state, included

Since the native input stays focusable, this tool also styles it properly: a visible :focus-visible outline appears on the custom box when the hidden input is focused, and the :indeterminate state (used for a parent checkbox when only some children are checked) gets its own look — both included by default, not left for you to add later.

Try Checkbox Style Generator →

#CustomCheckboxGenerator#CssCheckboxGeneratorAccessible#CustomCheckboxKeyboardFocusNotWorking#CheckboxDisplayNoneAccessibilityBug#CssCheckboxIndeterminateState