Accessibility
Accessibility (often written a11y) means everyone can use your site — including people who are blind, use only a keyboard, or have low vision. Good HTML gets you 80% of the way for free.
On this page · 6 min · Advanced
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 6 min
- Difficulty
- Advanced
- Updated
- Oct 28, 2026
Learning objectives#
- Explain who accessibility helps
- Use native elements that are keyboard-accessible by default
- Label forms, images and icons properly
- Use ARIA only when HTML is not enough
- Test a page with the keyboard and a screen reader
Explanation#
Around one in six people has a disability. Some use screen readers that read the page aloud, some use only a keyboard, some zoom to 200% or more.
Native elements come with accessibility built in: a <button> can be focused with Tab, pressed with Enter or Space, and is announced as “button”. A <div onclick> has none of that.
Everything needs a name a screen reader can say: <label> for inputs, alt for images, text or aria-label for icon-only buttons.
ARIA attributes (aria-label, aria-expanded, role) add meaning when HTML has no suitable element. The first rule of ARIA: if a native element exists, use it instead.
Never remove the focus outline without replacing it — keyboard users need to see where they are.
Code example: Accessible vs inaccessible#
<style>
.bad { color:#bbb; cursor:pointer; }
button:focus-visible { outline: 3px solid #2965f1; outline-offset: 2px; }
</style>
<!-- ✗ Not focusable, not announced, low contrast -->
<div class="bad" onclick="alert('Saved')">Save</div>
<!-- ✓ Keyboard + screen reader friendly -->
<button type="button" onclick="alert('Saved')">Save</button>
<!-- ✓ Icon-only button with an accessible name -->
<button type="button" aria-label="Close menu">✕</button>
<!-- ✓ Toggle that announces its state -->
<button type="button" aria-expanded="false" aria-controls="menu"
onclick="const o=this.getAttribute('aria-expanded')==='true';this.setAttribute('aria-expanded',!o);menu.hidden=o">
Menu
</button>
<ul id="menu" hidden><li><a href="#">Home</a></li></ul>
<!-- ✓ A skip link lets keyboard users jump past the menu -->
<a href="#main">Skip to main content</a>
Try pressing Tab: the grey “Save” div is skipped, but every real button receives a visible blue focus ring.
Step-by-step explanation#
- The div looks clickable but cannot be reached with Tab and is announced as plain text.
- The <button> works with mouse, keyboard and screen readers automatically.
- aria-label gives the ✕ icon a spoken name: “Close menu, button”.
- aria-expanded tells screen readers whether the menu is open or closed.
- :focus-visible draws a clear outline for keyboard users only.
- A “skip link” at the top of real pages lets keyboard users jump straight to <main id="main">.
Real-world use case#
Government, banking and education sites are legally required to be accessible in many countries (WCAG 2.2 AA). Accessible sites also work better for everyone — on phones, in sunlight, with a broken mouse.
Common mistakes#
This makes the page unusable for keyboard users. Style :focus-visible instead of removing it.
“Fields in red are required” fails for colour-blind users. Add text or an icon too.
<div role="button" tabindex="0"> still needs keyboard handling you must write yourself. A <button> is simpler and correct.
Best practices#
- Use native HTML elements first
- Every input has a label, every image has alt, every icon button has a name
- Keep text contrast at least 4.5:1
- Test by unplugging your mouse and using only Tab, Enter, Space and arrow keys
- Try a screen reader: NVDA (Windows) or VoiceOver (Mac / iPhone)
Remember this#
If you can’t Tab to it, a keyboard user can’t use it.
First rule of ARIA: don’t use ARIA (if HTML can do it).
Every control needs a name a screen reader can say out loud.
Practice exercise#
Your task: Make this accessible: <div onclick="search()"><img src="search.svg"></div>
Need a hint?
Show solution
<button type="button" onclick="search()" aria-label="Search">
<img src="search.svg" alt="">
</button>
Mini quiz#
What is the best element for a clickable “Save” action?
Want more? Practise all HTML MCQs · HTML interview questions
My notes#
Saved in this browser.