Checkbox Animated
CSS-only checkbox: the indigo-bordered square fills in and a white tick grows in 0.2 s, on top of a real native checkbox that works from the keyboard.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Forms has 20 effects, including 2 free. Explore the category →
3 usage examples



How it works
The block is a <label class="cbx-check"> holding three things: the real <input type="checkbox">, the drawn square .cbx-box and the text. The real checkbox is made invisible (opacity: 0) but stays exactly under the square, at its size: it receives clicks, focus and the checked state, and the form sends it with its name and value. A click anywhere on the text checks it too, since everything sits in the label.
The drawing follows the native state through the input:checked + .cbx-box selector. The 24 px square, with a 2 px #6366f1 border, takes an indigo fill (0.3 s transition). The tick is the ::after pseudo-element: a 6 × 12 px rectangle with only its right and bottom borders drawn, rotated 45°. At rest it is at scale(0); checked, it goes to scale(1) in 0.2 s: the tick grows from its centre.
No JavaScript. Classes are prefixed cbx- and the .fx-0294-root root (dark background, 300 px tall) is just a display frame: in a real form, remove its min-height and background, and the text then takes your page's colour.
Accessibility
- Real checkbox: the native element stays in the page (no
display:noneorvisibility:hidden): Tab reaches it, Space checks it, a screen reader announces "checkbox, Accept the terms, not checked". - Visible focus: on keyboard focus, a light
#a5b4fcring is drawn around the square (input:focus-visible + .cbx-box). - Hit area: the whole row (square + text) can be clicked or tapped, not only the 24 px square.
- Reduced motion: under
prefers-reduced-motion: reduce, the fill and the tick appear without transition. - Required: for a box that must be accepted before sending, add
requiredto the input: the browser blocks the send and shows its own message.
Browser compatibility
CSS only: :checked, adjacent sibling selector, pseudo-element and transform. Measured in Chromium 151, Firefox 153 and WebKit 26.5 (Playwright): two independent copies, Tab then Space, touch at 390 px, reduced motion. The focus ring needs :focus-visible (Chrome 86, Firefox 85, Safari 15.4).
Older browsers: the checkbox checks and animates, only the keyboard focus ring is missing.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0294-root">
<label class="cbx-check">
<input type="checkbox" name="terms" value="yes">
<span class="cbx-box" aria-hidden="true"></span>
<span class="cbx-text">Accept the terms</span>
</label>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Colour (CSS — border of .cbx-box and fill of input:checked + .cbx-box) |
#6366f1 | Change both to keep the square consistent checked and unchecked. |
Square size (CSS — width / height of .cbx-box and of the input) |
24px | For 20 px, also shift the tick (left / top of ::after) and give the invisible input the same size. |
Tick speed (CSS — transition of .cbx-box::after) |
transform .2s | Lengthen to .35s for a more visible tick. |
Shape (CSS — border-radius of .cbx-box) |
6px | 50% gives a round box, 2px a stricter square. |
Demo frame (CSS — .fx-0294-root) |
min-height 300px, #0a0a0f background, white text | Remove these three settings to place the checkbox in your form: the text takes the page's colour. |
Sent name (HTML — name and value) |
terms = yes | What your server receives when the box is checked; nothing is sent when it is not. |
FAQ
name and value go with the form like a normal checkbox.input.indeterminate = true in JavaScript and add an input:indeterminate + .cbx-box rule that draws a dash instead of the tick.<label class="cbx-check"> as many times as needed inside the root; each checkbox keeps its own state.