A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
<style>.demo { button:hover { transform:translateY(-1px); }; }</style><main class="demo">Example content</main>
Engineering judgment: Keep the state hierarchy coherent: hover can enrich, focus must identify keyboard position, active can acknowledge press, and disabled should explain non-interactivity visually.
The useful mental model here is practical: how transient interaction states communicate affordance and status without becoming contradictory. When a rule looks obvious but the browser produces something else, start by identifying which constraint or rendering phase is actually winning.
<style>.demo { button:focus-visible { outline:2px solid currentColor; }; }</style><main class="demo">Example content</main>
In production, Hover is not available to every input method, so it should never be the only state that tells a user what is interactive. That is the kind of bug that survives visual spot checks because the stylesheet is syntactically valid while the layout contract is wrong.
| Concern | What to inspect | Typical failure |
|---|---|---|
| Core behavior | Focus, Hover, Active, and Disabled States | Hover is not available to every input method, so it should never be the only state that tells a user what is interactive. |
| Production test | Real content and constraints | The rule works only for the demo values |
| Maintenance | Scope and override path | A later fix creates another exception |
The useful mental model here is practical: how transient interaction states communicate affordance and status without becoming contradictory. When a rule looks obvious but the browser produces something else, start by identifying which constraint or rendering phase is actually winning.
<style>.demo { button:active { transform:translateY(0); }; }</style><main class="demo">Example content</main>
Pressed state is useful here because it demonstrates focus, hover, active, and disabled states under a concrete input rather than as an abstract property list.
<style>.demo { button:disabled { opacity:.55; }; }</style><main class="demo">Example content</main>
Disabled state is useful here because it demonstrates focus, hover, active, and disabled states under a concrete input rather than as an abstract property list.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.