Form fields have states that CSS can detect, with no JavaScript.
| Pseudo-class | Matches |
|---|---|
:checked | A checked checkbox or radio button, or a selected option |
:disabled | A control that cannot be used |
:enabled | The opposite |
:required | A field marked required |
:optional | A field that is not required |
:valid, :invalid | Passing or failing its own validation rules |
:placeholder-shown | A field that is still showing its placeholder |
:checked in action
<style>
input[type="checkbox"]:checked + label { color: #1a5276; font-weight: bold; text-decoration: line-through; }
label { margin-left: 6px; }
</style>
<input type="checkbox" id="a"><label for="a">Buy a notebook</label><br>
<input type="checkbox" id="b" checked><label for="b">Buy a pen</label>
The + is the adjacent sibling selector: the label comes straight after the checkbox, so CSS can react to the checkbox state.
:disabled and :required
<style>
input:disabled { background: #eee; color: #888; cursor: not-allowed; }
input:required { border-left: 4px solid #d94a00; }
input { padding: 6px; margin: 4px; }
</style>
<input placeholder="Required field" required>
<input placeholder="Optional field">
<input placeholder="Disabled field" disabled>
A toggle switch with no JavaScript
A hidden checkbox plus a styled label makes a switch:
<style>
.switch input { position: absolute; opacity: 0; }
.switch label { display: inline-block; width: 52px; height: 28px; background: #bbb; border-radius: 999px; position: relative; cursor: pointer; transition: background .2s; }
.switch label::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; background: #fff; border-radius: 50%; transition: transform .2s; }
.switch input:checked + label { background: #27ae60; }
.switch input:checked + label::after { transform: translateX(24px); }
.switch input:focus-visible + label { outline: 3px solid #1a5276; outline-offset: 2px; }
</style>
<div class="switch"><input type="checkbox" id="sw"><label for="sw" aria-label="Notifications"></label></div>
The checkbox is still there and focusable, only invisible. This is why keyboard users and screen readers can still use it. More about styling forms in Form Validation States.