Accessibility & semantics

The custom checkbox stays hand-rolled until `::checkmark` actually ships

The custom checkbox stays hand-rolled until `::checkmark` actually ships

A styled checkbox is one of those components where the temptation to reach for a <div role="checkbox"> is enormous and the cost is invisible until the wrong person tries to use it. A keyboard user gets nothing. A screen reader user gets whatever ARIA glue you remembered to attach. A user with a switch device or voice control gets a control the browser does not know is a control. And you get a Jira ticket six months later.

Andy Bell's new post on Piccalilli sits inside that tension. It looks forward to a future where you can finally style the check mark itself — the ::checkmark pseudo-element in the W3C Forms Level 1 spec, paired with appearance: base on the native input — and then, in the same breath, tells you not to hold your breath. He notes that no browser currently appears to be working on shipping ::checkmark for checkboxes. So the rest of the piece is what a responsible custom checkbox looks like in the meantime.

Who this is for, and what breaks

The people who lose when a checkbox is not really a checkbox are not hypothetical. A user who tabs through your form expects the space key to toggle a checkbox. A user on a screen reader expects to hear the control's role and its checked state, in that order, without you having to spell either one out. A user with a form-filling tool expects the browser to recognise the field so autofill and validation work. Native <input type="checkbox"> gives you all of that for free. A styled div gives you none of it, and every attempt to bolt the missing pieces back on with ARIA has to be maintained forever.

That is the through-line of Andy's article, and it is the reason his workaround pattern begins where it does: with a real <input type="checkbox"> wrapped in a <label>. The label provides the accessible name and the click target; the input provides the role, the state, and the keyboard behaviour; styled spans inside the label do the visual work. Nothing about the semantics moves to CSS.

What ::checkmark is really promising

The promise of the Forms Level 1 pseudo-element is small and, once you sit with it, quite exciting. ::checkmark represents the indicator on checkboxes, radios and options — the tick, the dot, the mark — as a real element you can target from CSS. Paired with appearance: base, it is meant to let designers style native form controls without swapping them out for a re-implementation.

That is worth wanting. It closes the specific gap that has driven a generation of custom-checkbox patterns: designers who wanted a bespoke tick, developers who could not deliver one without abandoning the native control. Andy's point is that today the only CSS handle on the native check is accent-color, and that is not enough to satisfy most designs. So people go and build the div.

His workaround is the version of that build that does not throw the semantics away.

The read from here

The unglamorous conclusion is that the accessible checkbox in 2026 looks a lot like the accessible checkbox in 2016. The input is still an <input type="checkbox">. The label is still a <label> wrapping it. The visual is still built up from styled elements you draw yourself. What has changed is that we can now see the exit ramp — a spec, a pseudo-element, a companion appearance keyword — and we can see that the ramp has not been built yet.

Do not pre-emptively refactor for a feature that has not shipped. Do not pre-emptively abandon the native control because a nicer one is coming. When you reach for a custom checkbox on your next PR, use this checklist:

  • The input is a real <input type="checkbox">, not a div with role="checkbox".
  • The <label> wraps the input, so clicking the label toggles it and there is no need to wire for and id.
  • The visual indicator is drawn with elements inside the label, not by faking the input.
  • Focus is visible on the input itself, not only on the graphic.
  • The checked state is announced by the browser, not narrated by ARIA you wrote.

When ::checkmark and appearance: base do land, the payoff for authors who stayed on the native control will be a small stylesheet change. The payoff for authors who built a div will be another rewrite.

Source: Piccalilli (piccalil.li)

Related
Accessibility & semantics

Customizable `<select>` is still a `<select>`: keep the text

WebKit's golden rule for the new customizable `<select>` is the rule we should have been following all along: every option needs real text, even when icons or swatches do the visual work.

June 20, 2026
Browser releases

Safari Technology Preview 252 adds @supports named-feature(), unprefixed user-select and two accessible-name fixes

WebKit's 11 September preview adds a named-feature() function to @supports, exposes CSSConditionRule.supports and CSSMediaRule.matches on the CSSOM, ships the unprefixed user-select property, allows percentage values in text-decoration-inset, and cleans up two accessible-name bugs around display: contents and list markers.

September 12, 2026
CSS & layout

::highlight() with a text-shadow safety net

The CSS Custom Highlight API lets you paint arbitrary text ranges from JavaScript, no wrapper spans required. A text-shadow fallback keeps the effect intact when the API is not there.

August 6, 2026