aria text can help with keyboard navigation

Accessibility Basics: ARIA, Alt Text & Keyboard Navigation – Day 11 of Full Stack Web Development Roadmap

aria text can help with keyboard navigation

Accessibility Basics: ARIA, Alt Text & Keyboard Navigation – Day 11 of Full Stack Web Development Roadmap

Day 11: Accessibility Basics – ARIA, Alt Text & Keyboard Navigation

We’ve built a clean semantic layout, embedded media, connected pages, and structured forms. Now let’s make sure everyone can actually use them.

There’s a persistent myth that accessibility is a post-launch checklist, a plugin you install, or a legal hurdle you clear after shipping. It’s none of those things. Accessibility is a structural habit baked into your HTML from line one. When you skip it, you don’t just exclude users—you build fragile markup that breaks on mobile, fails search engine crawlers, and frustrates power users who rely on keyboards or screen readers.

In this post, we’ll cover the foundational patterns that make your HTML truly usable. You’ll learn exactly when to use ARIA (and when to avoid it), how to enforce predictable keyboard navigation, how to audit alt text strategically, and how to verify your work using built-in DevTools and free testing workflows. We’re keeping this focused on core attributes and early-stage habits. Complex focus traps, live regions, and framework-specific a11y patterns will come later. Today is about building a solid, testable baseline.

🎯 What You’ll Learn Today

By the end of this post, you will:

  • Understand the First Rule of ARIA and why native HTML always wins
  • Apply essential aria-* attributes (aria-labelaria-expandedaria-hiddenrole) correctly
  • Enforce predictable keyboard navigation with tabindex, focus indicators, and skip links
  • Audit and fix alt text using purpose-driven rules (informative, functional, decorative)
  • Verify accessibility using DevTools, automated linters, and basic screen reader testing

correct mindset is needed for using aria properly
correct mindset is needed for using aria properly

1. The Mindset & The First Rule of ARIA

ARIA stands for Accessible Rich Internet Applications. It’s a set of attributes that explicitly tell assistive technology how to interpret UI elements that native HTML doesn’t fully describe on its own. But before you reach for any aria-* attribute, memorize this rule:

Don’t use ARIA if a native HTML element already does the job.

<button><nav><input>, and <img alt=""> are inherently accessible. They carry built-in keyboard support, focus management, and screen reader announcements. ARIA is a patch for semantic gaps, not a replacement for proper markup. Misusing it actually breaks accessibility more often than omitting it entirely.

🔹 Micro-Exercise 1: Semantic vs. ARIA Patch Create a new file named a11y.html with the standard HTML5 boilerplate. Inside <body>, add:

<!-- Native (preferred) -->
<button>Click Me</button>

<!-- ARIA patch (acceptable only if native isn't possible) -->
<div role="button" tabindex="0" aria-label="Custom Click">Click Me</div>
Code language: HTML, XML (xml)

Save and open in your browser. Press Tab to move focus between them. Both receive focus, but notice how the native <button> already has browser default focus styling and built-in keyboard behavior (Space/Enter triggers it). The <div> requires manual tabindex and won’t respond to keyboard events without JavaScript. Open DevTools → More Tools → Accessibility → Tree view. Both announce as “button,” but the native one inherits everything automatically. Remember this hierarchy.


2. Core ARIA Patterns for Real UI

Beginners overcomplicate ARIA. In practice, four attributes cover 80% of early projects:

  • aria-label: Names an element when visible text isn’t present (icon buttons, close ×).
  • aria-expanded="true/false": Tells screen readers whether a dropdown/accordion is open or closed.
  • aria-hidden="true": Removes decorative or non-interactive elements from the accessibility tree so they’re skipped entirely.
  • role: Assigns semantic meaning when HTML falls short (role="dialog"role="alert"role="navigation").

🔹 Micro-Exercise 2: Apply Core Attributes Keep a11y.html open. Replace the current content inside <body> with this structure:

<main id="main-content">
  <h1>Accessible Menu Demo</h1>
  <button id="menu-btn" aria-expanded="false" aria-controls="dropdown">
    <span aria-hidden="true"></span> Menu
  </button>

  <ul id="dropdown" hidden>
    <li><a href="#">Profile</a></li>
    <li><a href="#">Settings</a></li>
  </ul>
</main>
Code language: HTML, XML (xml)

Save, refresh. Open DevTools → Accessibility pane. Verify the button announces “Menu, button, collapsed.” The hamburger icon is skipped (aria-hidden). The aria-controls explicitly links the button to the dropdown. The hidden attribute keeps it off-screen until you toggle it via JS later. This is how you make custom UI readable without bloating markup.


3. Keyboard Navigation Fundamentals

Roughly 30% of power users and virtually all assistive tech users navigate entirely by keyboard. HTML’s default Tab order follows DOM order. Break it, and you break accessibility.

  • tabindex="0": Adds a custom element to the natural tab flow.
  • tabindex="-1": Makes an element programmatically focusable (via JS) but removes it from sequential tab order.
  • Visible focus: Never remove outline without providing a clear :focus-visible replacement. It’s a usability requirement and a WCAG baseline.
  • Skip links: Hidden until focused, they jump users past repetitive headers straight to <main>.

🔹 Micro-Exercise 3: Enforce Keyboard Flow Add this to the very top of <body> in a11y.html (before <main>):

<a href="#main-content" class="skip-link">Skip to main content</a>
Code language: HTML, XML (xml)

Add this <style> block inside <head>:

<style>
  .skip-link {
    position: absolute;
    left: -9999px;
    top: auto;
    padding: 0.5rem 1rem;
    background: #000;
    color: #fff;
    z-index: 100;
  }
  .skip-link:focus {
    left: 0;
  }
  :focus-visible {
    outline: 3px solid #0d6efd;
    outline-offset: 2px;
  }
</style>
Code language: HTML, XML (xml)

Save, refresh, press Tab. Watch the skip link appear. Press Enter. Focus jumps directly to #main-content. This takes 30 seconds to implement and saves users minutes of navigation fatigue. :focus-visible ensures keyboard users get a clear indicator while mouse users avoid the distracting ring.

4. Alt Text Revisited: The Audit Framework

We covered alt basics on Day 5, but real-world a11y requires a consistent audit mindset. The question isn’t “describe it”—it’s “what’s its purpose here?”

  • Informative: Conveys content → write a concise, specific description.
  • Functional: Acts as a link or button → describe the action (alt="Search").
  • Decorative: Purely visual → alt="" (empty string, never omitted).

🔹 Micro-Exercise 4: Audit & Fix Add two images inside your <main> tag, right below the dropdown:

<!-- Informative -->
<img src="https://via.placeholder.com/300x150?text=Q3+Growth+Chart" alt="Bar chart showing 42% growth in Q3 2026">

<!-- Decorative -->
<img src="https://via.placeholder.com/300x10?text=Divider" alt="" role="presentation">
Code language: HTML, XML (xml)

Save, refresh. Open DevTools → Accessibility → select each <img>. Verify the first announces its description, the second is completely skipped. Run the page through the axe DevTools browser extension. You should see zero contrast or missing alt violations. This is your baseline for any media-heavy page.


5. Beginner Pitfalls & Quick Fixes

Let’s address the traps that break accessibility in Week 3:

  • ARIA overuse: Slapping role and aria-* on everything → Fix: use native HTML first. Only patch when semantics genuinely fail.
  • Broken tab order: Negative tabindex or JS focus traps without escape → Fix: keep DOM order logical, test with Tab/Shift+Tab manually.
  • Invisible focusoutline: none without replacement → Fix: always pair with :focus-visible using high-contrast borders or shadows.
  • Relying solely on automated linters: Tools like axe/Lighthouse catch ~30% of issues → Fix: combine automated scans with manual keyboard navigation and screen reader testing.
  • Debug tip: Chrome DevTools → Accessibility tab → click “Show all nodes” → verify every interactive element has a computed name and role. If it says generic or null, it’s invisible to assistive tech.

6. Synthesis Exercise: Build & Test an Accessible Toggle

Combine everything into one cohesive, production-ready file. Keep a11y.html open and make these final adjustments:

  1. Ensure your <main> has id="main-content" and the skip link points to it.
  2. Verify the menu button uses aria-expandedaria-controls, and aria-hidden on the icon.
  3. Add tabindex="0" to any custom interactive elements you might add later.
  4. Apply :focus-visible globally in your <style> block (already done).
  5. Test the full page:
    • Press Tab repeatedly. Verify logical focus order (skip link → heading → button → links → images)
    • Click the toggle. Watch aria-expanded change in DevTools Elements panel
    • Run axe DevTools extension. Fix any flagged issues
    • (Optional) Turn on VoiceOver (Mac) or NVDA (Windows). Navigate using Tab + VoiceOver/NVDA keys. Listen for clear, contextual announcements.

Stretch prompt: Temporarily remove aria-expanded="false" from the button. Test with a screen reader. How does the announcement change? Why does explicit state management matter for dynamic UI, even when the visual toggle works perfectly?


Key Takeaways

  • Native HTML is inherently accessible. Use ARIA only when semantics fall short- aria-labelaria-expanded, and aria-hidden cover most early UI needs
  • Keyboard flow depends on DOM order, tabindex, and visible :focus-visible styles
  • alt strategy is purpose-driven: informative, functional, or empty for decorative
  • Verify with DevTools Accessibility pane, automated linters, and manual keyboard/screen reader tests

What’s Next

In the next post, we’ll finally consolidate everything we’ve learned into the HTML Project: Build Semantic Static Webpage. You’ll combine structure, media, forms, accessibility, and semantic layout into a single, production-ready page that passes real-world validation checks.

Preview question: When reviewing your final HTML page before considering it “complete,” what 3 accessibility checks will you run first? Jot down your list. We’ll apply it next.


← Day 10: Semantic HTML Layout Elements | Day 11 | Day 12: HTML Project — Build Semantic Static Webpage →

Author

  • Naoman Saeed

    I’m a self-taught developer building my way from code experiments to full-stack web solutions. At trogdyne.com, I share what I learn — from Flask and Docker to the realities of running a one-person digital agency in Pakistan.

Leave a Reply

Your email address will not be published. Required fields are marked *