Before this lesson

Understand CSS selectors, states and the cascade. Promises and asynchronous programming are not required.

What you will be able to do

Style hover, keyboard focus, disabled and error states consistently while separating decoration from content.

Understand the mechanism

Pseudo-classes select element states or structural positions, while pseudo-elements represent a part or generated box. Decide whether the requirement describes state or decoration. Generated content should not be the sole carrier of essential instructions or errors.

Hover is a pointer state and is unreliable as the sole touch interaction. focus-visible provides focus styling. Use disabled for actual disabling rather than only reducing opacity, so appearance and behavior agree.

Scope state rules to components instead of changing every button globally. :where can supply low-specificity defaults. Prefer readable selectors and inspect the cascade before escalating with important declarations.

Check default, hover, focus, active and disabled states, including combinations. Keyboard focus must remain visible and disabled controls should not appear active. Use text for action outcomes rather than color alone.

Runnable example

Run HTML examples as separate .html files in a modern browser. Prepare resource files and multi-file modules as described in the lesson.

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Honeysuck practice</title></head><body>
<style>
.action{font:inherit;padding:.7rem 1rem;border:1px solid #176343;background:white;color:#174d37;border-radius:.5rem}
.action:hover:not(:disabled){background:#e5f2e8}
.action:focus-visible{outline:3px solid #785b00;outline-offset:4px}
.action:active:not(:disabled){transform:translateY(1px)}
.action:disabled{opacity:.55;cursor:not-allowed}
.note::before{content:"";display:inline-block;width:.5rem;height:.5rem;border-radius:50%;background:#176343;margin-right:.5rem}
</style><p class="note">Practice is available without an account.</p>
<button class="action">Start practice</button><button class="action" disabled>Already submitted</button>
</body></html>

Trace and verify

Hover the first button for a background change, Tab for an outline, and press for a slight shift. The disabled button cannot activate normally. Remove CSS temporarily: meaningful labels and instructions should remain understandable.

Common mistakes and boundaries

Pseudo-elements are not independent DOM controls. nth-child follows sibling position, not business identity, so it should not encode completion after filtering or insertion.

Practice challenge

Add a favorite toggle with aria-pressed and style the attribute while keeping explicit labels.

Reference solution and reasoning

Update aria-pressed and the label together, then let CSS read the attribute. Test repeated clicks and keyboard activation rather than changing only a class.

Further reading