LEARNING OBJECTIVES โต
- Understand the exact specification rules for HTML boolean attributes like
checked. - Differentiate between the declarative HTML attribute (
defaultChecked) and the live DOM state (checked). - Master how
<form>reset events interact with initial checked states. - Leverage the CSS
:checkedpseudo-class to build accessible custom toggle switches without JavaScript.
๐ The Mental Model & Story (Intuitive Foundation)
Imagine checking into a modern hotel room. When you first enter the room, the hotel management has already set the master light switch to ON and the smart thermostat to 72ยฐF.
+-------------------------------------------------------------+
| HOTEL ROOM PRESETS |
| |
| Master Power Switch: [ ON ] <-- Initial default setting |
| |
| You wake up & switch it: |
| Master Power Switch: [ OFF ] <-- Current live state |
| |
| You press "Restore Room Defaults" button: |
| Master Power Switch: [ ON ] <-- Restored from preset! |
+-------------------------------------------------------------+
If you flick the switch to OFF during your stay, you have modified the live state of the room. However, the hotel management system still remembers that the initial baseline state for this room was ON. If you press the "Restore Defaults" button on the wall console, the switch snaps right back to ON.
In web development, the checked attribute in your HTML markup is that initial hotel baseline preset. It tells the browser how checkboxes and radio buttons should be configured when the document is parsed or when a form is reset.
Technical Deep Dive & Specifications
HTML Boolean Attribute Rules
In standard HTML5, checked is a Boolean attribute.
The WHATWG specification defines a boolean attribute by a strict rule: The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.
Valid Ways to Declare a Checked Element:
<input type="checkbox" checked>
<input type="checkbox" checked="">
<input type="checkbox" checked="checked">
FATAL MISTAKE (Still evaluates to TRUE!):
<input type="checkbox" checked="false"> <-- TRUE! (Attribute is present!)
[!WARNING] In HTML, writing
checked="false"does NOT uncheck the box! Because the string"false"is present, the parser treats the boolean attribute as active (true). To make an element unchecked in raw HTML markup, you must completely omit the attribute.
DOM Property vs HTML Attribute: defaultChecked vs checked
When the browser parses HTML containing checked, it populates two distinct properties on the HTMLInputElement DOM interface:
+-------------------------------------------------------------------------------+
| DOM PROPERTY REFLECTION MATRIX |
+-------------------------------------------------------------------------------+
1. HTML Parsed:
<input type="checkbox" id="opt" checked>
|
+---> element.defaultChecked = true (Reflects the HTML content attribute)
+---> element.checked = true (The live interactive user state)
2. User Clicks the Checkbox (Unchecks it):
+---> element.defaultChecked = true (UNCHANGED! Initial markup is preserved)
+---> element.checked = false (UPDATED to reflect user action)
3. JavaScript calls form.reset():
+---> Browser copies defaultChecked into checked:
element.checked = element.defaultChecked (Becomes true again!)
| Property / Method | Target State | Mutates On User Click? | Resets On form.reset()? |
|---|---|---|---|
element.checked |
Live current state | Yes | Reverts to defaultChecked |
element.defaultChecked |
Initial baseline state | No | Remains constant |
element.setAttribute('checked', '') |
Initial baseline attribute | No | Updates defaultChecked |
The Form Reset Lifecycle
When a user triggers <button type="reset"> or script calls form.reset(), the browser executes the following algorithm:
- Iterates over all submittable controls within the form.
- For text inputs, assigns
input.value = input.defaultValue. - For checkboxes and radio buttons, assigns
input.checked = input.defaultChecked.
The CSS :checked Pseudo-Class
The CSS :checked pseudo-class matches any <input type="checkbox">, <input type="radio">, or <option> that currently has checked === true.
By combining :checked with CSS sibling combinators (+ or ~) or the modern :has() selector, you can build complex, animated UI widgets entirely in CSS without a single line of JavaScript.
CSS Selector Engine Combinators:
input:checked + label -> Targets label immediately following checked input
input:checked ~ .alert-box -> Targets sibling element anywhere after checked input
.card:has(input:checked) -> Targets parent card containing checked input
๐ป Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Line 77 (
checked): Declares the switch as active by default. This initializes bothdefaultChecked = trueandchecked = true. - Lines 54โ63 (
:checked + .slider): When the hidden input is checked, the adjacent.sliderspan turns green (#10b981) and shifts the inner circle 22px to the right via CSS transforms. - Lines 64โ67 (
:focus-visible): Ensures full accessibility compliance by displaying a prominent focus ring when the user tabs to the hidden switch. - Lines 100โ108 (Reset Listener): Demonstrates that pressing "Reset Form" automatically reverts
checkedback to its initialdefaultChecked(true).
Expected Browser Render Output
+-----------------------------------------------+
| Account Security Preferences |
| |
| Two-Factor Authentication (2FA) ( [O] ) | <-- Green Switch ON
| |
| defaultChecked: true |
| live checked: true |
| |
| [ Reset Form ] |
+-----------------------------------------------+๐๏ธ Hands-On Exercise
๐ฏ The Challenge: Build an Accessible Pure CSS Theme Switcher & Accordion
Instructions:
- Create a pure CSS collapsible FAQ accordion item without writing any JavaScript.
- Use a hidden
<input type="checkbox" id="faq-item-1">that starts unchecked. - Place a
<label for="faq-item-1">styled as a clickable accordion header (e.g., "How do I upgrade my account?"). - Place an accordion content
<div>immediately following the label containing FAQ answer text. - In CSS:
- Hide the content by default (
max-height: 0; overflow: hidden; opacity: 0; transition: all 0.3s;). - When the checkbox is
:checked, expand the content (max-height: 200px; opacity: 1;).
- Hide the content by default (
- Include a reset button to test restoring the collapsed state.
๐ Starter Code Sandbox
โ ๏ธ Common Pitfalls
- The
checked="false"Bug: Writing<input type="checkbox" checked="false">does NOT uncheck the box. Because boolean attributes evaluate totruewhenever present, this renders a checked box. - Manipulating
setAttributeInstead of Property: In JavaScript, executingcheckbox.setAttribute('checked', '')mutatesdefaultChecked, which will not toggle a live box that the user has already interacted with. Always usecheckbox.checked = trueorcheckbox.checked = false. - Breaking Accessibility on Custom Toggles: Hiding native inputs with
display: nonecompletely removes them from the accessibility tree, making custom switches impossible for keyboard-only and screen reader users to operate. Useopacity: 0; position: absolute;instead.
๐ก Pro Tips
- Pure CSS Dynamic Theming: You can place a single checkbox at the top of your document (
<input type="checkbox" id="theme-toggle">) and toggle entire dark/light mode themes across your website using:has(#theme-toggle:checked) body { --bg: #121212; --text: #ffffff; }. - Form Restoration with BFCache: When a user navigates away from a page and clicks "Back", browsers restore the user's live
checkedstate from the back-forward cache (BFCache) rather than re-evaluating the HTMLcheckedattribute.
๐ Key Takeaways
checkedis an HTML Boolean attribute; its mere presence sets the element totrue. To make it false, omit the attribute.- The HTML attribute sets the baseline
defaultCheckedstate; the live user interaction state is held inchecked. - Calling
form.reset()restores all checkboxes and radio buttons to their initialdefaultCheckedvalues. - The CSS
:checkedpseudo-class enables state-driven components (accordions, toggle switches, tabs) without JavaScript. - Always keep custom checkbox inputs focusable (
opacity: 0; position: absolute;) so keyboard users can navigate them with Tab and Space. - --