Building Custom Checkbox and Radio Designs

When accent-color Is Not Enough

For a fully custom shape or icon - not just a recolored native checkbox - the common technique is to visually hide the real input while keeping it functional and accessible, then build a fake control from other elements that reacts to its state.

The HTML Structure

<label class="custom-checkbox">
  <input type="checkbox">
  <span class="control"></span>
  Subscribe to updates
</label>

Hiding the Real Input Correctly

.custom-checkbox input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

The real checkbox must stay in the document and remain focusable and clickable by assistive technology - using display: none would remove it from the accessibility tree entirely, breaking screen reader support. This pattern keeps it technically present but visually invisible.

Styling the Visible Fake Control

.control {
  width: 20px;
  height: 20px;
  border: 2px solid #999;
  border-radius: 4px;
  display: inline-block;
}
.custom-checkbox input:checked + .control {
  background: #1d4ed8;
  border-color: #1d4ed8;
}

The :checked state of the real (hidden) input, combined with the adjacent sibling combinator, drives the visual appearance of the fake control right next to it - no JavaScript required.

Never Skip the Focus State

.custom-checkbox input:focus-visible + .control {
  outline: 2px solid #1d4ed8;
  outline-offset: 2px;
}

Because the real input is visually hidden, its focus state must be manually forwarded onto the visible fake control - forgetting this step is the most common accessibility bug in custom form control implementations.

Written by Lorens Mishra

Software Engineer Notes Management System Administrator

Continue reading

All CSS notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.