Binding an Input's Pseudo-Class States to Sibling Elements with CSS

In the article Build an Accessible Toggle Switch with React and SVG, I used a technique to bind the focus, checked, and disabled states of a hidden checkbox to adjacent html (or SVG) elements.

This is accomplished using the general sibling combinator in conjunction with the :checked, :disabled and :focus pseudo-class selectors.

There are other input and form-related pseudo-class selectors, all of which will work will work with this technique:

:checked, :default, :disabled, :enabled, :focus, :indeterminate, :in-range, :invalid, :optional, :out-of-range, :placeholder-shown, :read-only, :read-write, :required, :valid

I thought it was worth saving an example of how to do this for quick future reference.

For simplicity, this example simply affects the appearance of an adjacent <span class="label"> element.

Note: Nesting the input inside the label element is a valid way of associating the input's events (click, touch, etc.) to the label text (or other elements) without needing unique id attributes for your inputs and corresponding for attributes for your labels.

Example

This example illustrates how the concept works. The checked state of the input controls the style of the sibling span, changing the font style and adding a potato emoji using the :after pseudo-class:

Here's the code for making it work:

HTML:

<label>
  <input
    class="checkbox"
    type="checkbox"
    ariaLabel="check this box to receive a potato"
  />
  <span class="label">Potato</span>
</label>

CSS:

.checkbox:checked ~ .label {
  font-style: italic;
}

.checkbox:checked ~ .label:after {
  content: '🥔';
}

That's it! If you have any questions, let me know.