HTML Accessibility (a11y) — Complete Beginner's Guide
Web accessibility (often shortened to a11y — 11 letters between ‘a’ and ‘y’) means designing websites that everyone can use, including people with visual, hearing, motor, or cognitive disabilities. It’s not just a nice-to-have — it’s required by law in many countries and benefits every user.
What You’ll Learn
By the end of this tutorial, you’ll understand why accessibility matters, use semantic HTML landmarks for screen reader navigation, write effective alt text for images, apply ARIA attributes correctly, manage keyboard focus and navigation, ensure sufficient color contrast, and test your pages for accessibility issues.
Why Accessibility Matters
Imagine trying to use a website when you can’t see the screen. Or when you can’t use a mouse. Or when the text is too small and low-contrast to read. That’s the reality for millions of users every day.
Security note: Understanding Html Accessibility helps build more secure applications — a core principle at DodaTech, where tools like Durga Antivirus Pro and Doda Browser rely on solid implementation practices.
The numbers: About 1 in 5 people worldwide have some form of disability. That’s over 1 billion potential users. If your site isn’t accessible, you’re excluding 20% of your audience.
Real-world use: Screen reader users navigate websites by jumping between headings, landmarks, and links using keyboard shortcuts. If your page uses <div> for everything, a screen reader just sees a wall of text. If you use <h1>, <nav>, <main>, it becomes navigable.
Legal note: In the US, the ADA (Americans with Disabilities Act) applies to websites. In the EU, the Web Accessibility Directive requires public sector sites to be accessible. Lawsuits over inaccessible websites are increasing every year.
Where This Fits in Your Learning Path
flowchart LR
A["HTML & SEO"] --> B["**Accessibility (a11y)**"]
B --> C["HTML Style Guide"]
C --> D["CSS Tutorials"]
D --> E["Frontend-Ready Developer"]
style B fill:#f97316,stroke:#c2410c,color:#fff
style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
style E fill:#22c55e,stroke:#16a34a,color:#fff
Semantic Landmarks — The Foundation of Accessibility
Screen readers (like JAWS, NVDA, or VoiceOver) let users navigate by “landmarks” — sections of the page with defined purposes. Semantic HTML elements automatically create these landmarks:
| HTML Element | Implicit ARIA Role | Purpose |
|---|---|---|
<header> | banner | Site header (logo, title, nav) |
<nav> | navigation | Navigation links |
<main> | main | Primary content (use once) |
<article> | article | Self-contained content |
<section> | region | Thematic group (needs an accessible name) |
<aside> | complementary | Related but secondary content |
<footer> | contentinfo | Copyright, contact, links |
<!-- ✅ Accessible: semantic landmarks -->
<header>
<h1>My Site</h1>
<nav aria-label="Main navigation">
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h2>Article Title</h2>
<p>Content...</p>
</article>
</main>
<footer>
<p>© 2026 My Site</p>
</footer><!-- ❌ Not accessible: no landmarks, just divs -->
<div class="header">
<h1>My Site</h1>
<div class="nav">
<a href="/">Home</a>
</div>
</div>
<div class="content">
<div class="post">
<h2>Article Title</h2>
</div>
</div>Why it matters: A screen reader user can press a key to jump from <nav> to <main> to <footer>. With <div> elements, nothing is navigable.
Alt Text — Every Image Needs It
<!-- ✅ Informative image: describe what it shows -->
<img src="chart.png" alt="Bar chart showing Q1 revenue growth from $10K to $25K">
<!-- ✅ Decorative image: empty alt tells screen readers to skip it -->
<img src="divider-line.png" alt="" role="presentation">
<!-- ❌ Missing alt: screen reader reads the filename -->
<img src="chart.png">
<!-- ❌ Redundant alt: repeats surrounding text -->
<img src="logo.png" alt="logo">The Alt Text Decision Tree
- Does the image convey information? → Write a descriptive alt text
- Is the image decorative (border, spacer, background)? → Use
alt=""(empty) - Is the image a link? → Describe the destination, not the image
- Is the image text? → Write the same text as alt (but avoid text-in-images)
Good alt text: “A golden retriever puppy sitting on grass holding a tennis ball” Bad alt text: “dog” (too vague), “IMG_0425.jpg” (useless), “image” (redundant)
ARIA — When HTML Isn’t Enough
ARIA (Accessible Rich Internet Applications) extends HTML when semantic elements aren’t enough. The first rule of ARIA: don’t use it if you can use a native HTML element.
Common ARIA Attributes
| Attribute | When to Use |
|---|---|
aria-label | When an element has no visible label (e.g., an icon-only button) |
aria-labelledby | When you want to use existing text as the label |
aria-describedby | To provide a longer description |
aria-hidden="true" | To hide decorative elements from screen readers |
aria-expanded | To indicate if a collapsible section is open/closed |
aria-live | To announce dynamic content changes (polite/assertive) |
<!-- Icon-only button needs aria-label -->
<button aria-label="Close dialog" onclick="closeDialog()">
✕
</button>
<!-- Live region announces dynamic updates -->
<div aria-live="polite" aria-atomic="true">
Cart has 3 items.
</div>
<!-- Progress indicator needs role -->
<div role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100">
70%
</div>The ARIA Rule
“No ARIA is better than bad ARIA.” — W3C
Only use ARIA when:
- You can’t use a semantic HTML element
- You’re building a custom interactive widget (tab panel, accordion, modal)
- A native element doesn’t provide enough information
If you put role="button" on a <div> but forget keyboard handling, it’s less accessible than just using <button>.
Keyboard Navigation — No Mouse Required
Many users navigate entirely with the keyboard — tab key to move forward, Shift+Tab to move back, Enter/Space to activate.
Focus Management
<!-- Skip link: lets keyboard users skip repetitive nav -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<!-- Tabindex values -->
<button tabindex="0">Normal focus (0 is natural order)</button>
<button tabindex="-1">Programmatic focus only (not tabbable)</button>
<!-- DON'T use positive tabindex values -->
<button tabindex="5">Never do this</button>
<button tabindex="1">It creates a confusing order</button>The tabindex rule:
tabindex="0"— Element is focusable in natural tab ordertabindex="-1"— Element is focusable only via JavaScript (.focus()), not tabtabindex="5"(or any positive number) — Don’t use this. It overrides natural order and creates confusing navigation
Focus Indicators
Never remove the focus outline without providing an alternative:
/* ❌ Bad: removes focus indication entirely */
*:focus { outline: none; }
/* ✅ Good: custom focus style that's still visible */
*:focus { outline: 2px solid #667eea; outline-offset: 2px; }Color Contrast
Text must have sufficient contrast against its background. The WCAG (Web Content Accessibility Guidelines) standard requires:
| Level | Contrast Ratio | Who It Serves |
|---|---|---|
| AA (normal text) | 4.5:1 | Most users with visual impairments |
| AA (large text) | 3:1 | Text 18px+ or 14px+ bold |
| AAA (normal text) | 7:1 | Users with severe visual impairments |
Use a contrast checker tool (WebAIM provides a free one) to verify your color combinations.
/* ❌ Bad contrast: light gray on white */
body { color: #999; background: #fff; }
/* ✅ Good contrast: dark gray on white */
body { color: #333; background: #fff; }Accessible Forms
Forms are a common pain point for screen reader users. Every input needs a label:
<!-- ✅ Correct: label linked by 'for' attribute -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" required>
<!-- ✅ Correct: aria-label for icon-only context -->
<input type="search" aria-label="Search the site">
<!-- ❌ Wrong: placeholder as label (disappears on typing) -->
<input type="email" placeholder="Email address">Never rely on placeholders as labels. Placeholders disappear when the user types, leaving screen reader users with no idea what the field is for.
Error Messages
<label for="phone">Phone number</label>
<input type="tel" id="phone" name="phone"
aria-describedby="phone-hint phone-error">
<span id="phone-hint">Format: (555) 123-4567</span>
<span id="phone-error" role="alert" aria-live="polite"></span>Complete Accessible Page Template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Accessible Page</title>
<style>
.skip-link { position: absolute; top: -40px; left: 0; background: #333; color: white; padding: 8px; z-index: 100; }
.skip-link:focus { top: 0; }
:focus { outline: 2px solid #667eea; outline-offset: 2px; }
body { font-family: system-ui, sans-serif; color: #333; background: #fff; line-height: 1.6; margin: 0; }
</style>
</head>
<body>
<a href="#main" class="skip-link">Skip to main content</a>
<header>
<h1>My Accessible Site</h1>
<nav aria-label="Main">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
</header>
<main id="main">
<h2>Welcome</h2>
<p>This page is built with accessibility in mind.</p>
<img src="welcome.png" alt="Welcome illustration showing diverse users accessing the web" loading="lazy">
<form>
<label for="name">Your name</label>
<input type="text" id="name" name="name" required>
<button type="submit">Submit</button>
</form>
</main>
<footer>
<p>© 2026 DodaTech</p>
</footer>
</body>
</html>Common Accessibility Mistakes
1. Missing Skip Link
<!-- ❌ Wrong: keyboard users must tab through 20 nav links each time -->
<nav>
<a href="/">Home</a><a href="/products">Products</a><!-- ...18 more links... -->
</nav>
<main>
<!-- content -->
</main>
<!-- ✅ Correct: skip link jumps past navigation -->
<a href="#main" class="skip-link">Skip to main content</a>
<nav>...</nav>
<main id="main">...</main>2. Using placeholder as a Label
<!-- ❌ Wrong: placeholder disappears on typing -->
<input type="text" placeholder="Search">
<!-- ✅ Correct: proper label -->
<label for="search">Search</label>
<input type="text" id="search">3. Removing Focus Outlines
/* ❌ Wrong: keyboard users can't see where they are */
* { outline: none; }
/* ✅ Correct: visible focus indicator */
:focus { outline: 2px solid #667eea; outline-offset: 2px; }4. Low Contrast Text
<!-- ❌ Wrong: #999 on white fails contrast checks -->
<p style="color: #999;">Some fine print</p>
<!-- ✅ Correct: #555 is readable -->
<p style="color: #555;">Some fine print</p>5. Forgetting lang Attribute
<!-- ❌ Wrong: screen reader uses wrong pronunciation -->
<html>
<!-- ✅ Correct: tells screen reader to use English -->
<html lang="en">SEO benefit: Accessible pages often rank better. Google uses many of the same signals — clear headings, descriptive link text, semantic structure, image alt text — for both SEO and accessibility.
Try It Yourself
An accessible page with skip link, form labels, and ARIA:
Common Mistakes Beginners Make
1. Skipping the Fundamentals
Many beginners jump straight to advanced topics without mastering the basics. Take time to understand the core concepts before moving on.
2. Not Practicing Enough
Reading tutorials without writing code leads to shallow understanding. Code along with every example and experiment on your own.
3. Ignoring Error Messages
Error messages tell you exactly what went wrong. Read them carefully — they usually point to the line and type of issue.
4. Copy-Pasting Without Understanding
It’s tempting to copy code from tutorials, but typing it yourself and understanding each line builds real skill.
5. Giving Up Too Early
Every developer hits frustrating bugs. Take breaks, ask for help, and remember that struggling is part of learning.
Practice Questions
Q1: What is a skip link and why is it important? A skip link is the first focusable element on the page that jumps to the main content. It lets keyboard users bypass repetitive navigation links.
Q2: When should you use When an element has no visible text label — for example, an icon-only button (like ✕ for close) needs aria-label?aria-label="Close" so screen readers announce its purpose.
Q3: What’s the minimum color contrast ratio for normal text under WCAG AA? 4.5:1. For large text (18px+ or 14px+ bold), the minimum is 3:1.
Q4: Why shouldn’t you use Placeholder text disappears when the user types, so screen reader users can’t tell what the field is for after they start entering data.placeholder as a label?
Q5: What does It tells screen readers to announce content changes in that element, but to wait until the user is idle (polite mode). Use aria-live="polite" do?assertive for urgent messages like errors.
Challenge
Take a non-accessible page and fix it:
- A page with a
<div>navigation (fix: use<nav>) - Images without alt text (fix: add descriptive alt)
- A form with placeholder-only inputs (fix: add
<label>elements) - No skip link (fix: add one)
- Low contrast text (#aaa on white) (fix: darken to #555)
- No
langattribute (fix: addlang="en")
Frequently Asked Questions
What’s Next?
Now complete HTML with the style guide and reference:
What’s Next
Congratulations on completing this Html Accessibility tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro