Every user should be able to navigate the web comfortably. In this post, we will explore accessibility and how to make interfaces more inclusive with semantic HTML, focus control, and assistive-technology hints. This chapter again follows the concept → code → reasoning cadence.
Key terms
- Semantic HTML: markup that uses tags such as
header,nav, andsectionso roles are clear from the element names alone. - ARIA attributes: properties like
aria-labeloraria-livethat supplement assistive technologies when semantics are not enough. - Focus trap: a control technique that keeps
Tabnavigation inside a modal so focus does not leak out. roleattribute: explicitly defines an element’s role so screen readers can announce it precisely.
Core ideas
- Semantic HTML: communicate meaning with tags like
section,nav,button, andlabelso structure is predictable. - ARIA attributes: use helpers such as
aria-live,aria-expanded, andaria-controlsto add context when markup alone falls short. - Focus flow: design the order in which keyboard users traverse with
Tab, applyingtabindexand callingfocus()purposefully. - Live regions: add attributes like
aria-live="polite"near status text so assistive tech announces updates automatically.
Semantic structure
Start by combining semantic tags with navigation labels so the screen layout is self-explanatory.
<header>
<h1>Student schedule dashboard</h1>
<nav aria-label="Jump to page sections">
<a href="#tasks">Tasks</a>
<a href="#stats">Stats</a>
</nav>
</header>
<section id="tasks" aria-labelledby="tasks-heading">
<h2 id="tasks-heading">Task list</h2>
<ul role="list" class="task-list"></ul>
</section>
Adding aria-label and aria-labelledby ties headings to regions so screen readers can guide users rapidly.
Focus control for modals
Next, control modal focus so users never lose track of where they are.
const addButton = document.querySelector(".task-add");
const modal = document.querySelector("#task-modal");
const modalClose = modal?.querySelector(".modal-close");
function openModal() {
modal?.classList.add("is-open");
modal?.setAttribute("aria-hidden", "false");
modal?.setAttribute("aria-modal", "true");
modal?.querySelector("input")?.focus();
}
function closeModal() {
modal?.classList.remove("is-open");
modal?.setAttribute("aria-hidden", "true");
addButton?.focus();
}
addButton?.addEventListener("click", openModal);
modalClose?.addEventListener("click", closeModal);
Send focus into the modal when it opens and return it to the trigger button when it closes so keyboard users never feel stranded.
Live regions for feedback
Create a live region for state messages so feedback is read aloud automatically.
<div class="form-feedback" role="status" aria-live="polite"></div>
const feedback = document.querySelector(".form-feedback");
function showFeedback(message, type = "info") {
if (!feedback) return;
feedback.textContent = message;
feedback.className = `form-feedback is-${type}`;
}
form?.addEventListener("submit", (event) => {
event.preventDefault();
showFeedback("Saving...", "info");
saveTask().then(() => showFeedback("Saved!", "success"));
});
Using role="status" with aria-live="polite" ensures assistive technologies announce these state changes.
Focus styles
Finish by defining focus styles so the current position is obvious.
:focus-visible {
outline: 3px solid #1ba784;
outline-offset: 4px;
}
[tabindex="-1"]:focus {
outline: none;
}
Clear focus styling helps keyboard users confirm their place instantly.
Why it matters
- School projects and competitions often include accessibility criteria; mastering the basics improves evaluations.
- Semantic structure and ARIA hints also raise SEO quality.
- A predictable focus flow benefits everyone: when the keyboard alone is enough, testing speed goes up.
Practice
- Follow along: apply semantic tags to headers, main sections, buttons, and forms, then add
aria-labelandaria-labelledbylinks. - Extend: build a modal that moves focus on open/close while toggling
aria-hiddenandaria-modal. - Debug: tour the UI with only the Tab key, spot places where focus disappears or escapes, and fix them with
tabindexplus explicitfocus()calls. - Done when: a screen reader (VoiceOver, NVDA, etc.) announces every key element and the full workflow operates via keyboard alone.
Wrap-up
Accessibility is not an add-on—it is a default you embed from the start. Next we will catalog reusable UI patterns and see how to keep these accessibility principles intact.
💬 댓글
이 글에 대한 의견을 남겨주세요