What you'll learn
Accessible interfaces begin with semantic HTML and a state model that keeps visuals, focus, keyboard behavior, and assistive-technology announcements synchronized.
By the end of this lesson, you'll be able to:
- Choose native semantics before ARIA
- Manage focus after state changes
- Build state-driven keyboard interactions
Core mental model
Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.
| Concept | What it means | Decision rule |
|---|---|---|
| Native semantics | Built-in role, keyboard behavior, and form integration | Choose the correct element before adding ARIA |
| Focus management | Programmatic focus follows meaningful context changes | Move focus only when users would otherwise be lost |
| ARIA state | Accessibility metadata mirrors UI state | Update from the same source of truth as visuals |
Professional workflow
Build the behavior in small, observable steps. Each step should leave something you can inspect or test.
- Describe the accessible interaction boundary: inputs, outputs, state, timing, and expected failures.
- Implement the smallest correct path with names that expose intent.
- Add edge cases and failure handling before introducing abstractions.
- Verify behavior with realistic data and one deliberately adversarial example.
- Refactor only after the observable behavior is protected.
Make behavior observable
Guided code lab
Synchronize a disclosure
A native button controls one region and exposes the same open state.
const button = document.querySelector("#topics-button");
const panel = document.querySelector("#topics-panel");
button.addEventListener("click", () => {
const open = button.getAttribute("aria-expanded") === "true";
button.setAttribute("aria-expanded", String(!open));
panel.hidden = open;
});Focus after adding content
A newly displayed error summary becomes the next meaningful reading position.
function showErrors(messages) {
const summary = document.querySelector("#errors");
summary.replaceChildren(...messages.map(message => {
const item = document.createElement("p");
item.textContent = message;
return item;
}));
summary.hidden = false;
summary.focus();
}Production practice
Contract
Keep the accessible interaction API explicit: accepted state, emitted events, DOM ownership, and cleanup.
Verification
Test with keyboard input, missing elements, repeated initialization, and teardown—not only a mouse happy path.
Operations
Measure user-visible latency and remove listeners, observers, object URLs, or media tracks when the feature ends.
Common failure mode
Independent workshop
Build an accessible modal dialog and document its focus lifecycle.
Your finished workshop must include:
- Native open/close controls
- Initial, trapped, and restored focus
- Escape handling and a meaningful label
Definition of done
Recap & quick check
Key takeaways
- Native semantics carry behavior
- ARIA reflects—not creates—interaction
- Focus follows meaningful context
- One state source drives every representation
Quick check
1. What is the first rule of ARIA?
2. What should aria-expanded mirror?
3. Where should focus return after a dialog closes?
Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.