What is web accessibility, and how does HTML help?
Web accessibility (a11y) means people with disabilities can use the site, whether they use a screen reader, only a keyboard, or have low vision. Most of it is correct HTML: semantic elements,
alttext, labels on inputs,langon<html>, and keyboard access with visible focus. The standard is WCAG.Why should you set the
langattribute on<html>?langtells browsers and assistive technology the page's language, so screen readers pick the right pronunciation and browsers offer translation.<html lang="en"> ... <p>The Hindi word <span lang="hi">नमस्ते</span> means hello.</p>Without it, an English screen reader may read a Hindi page with English pronunciation. Values are language codes with an optional region:
en,hi,en-IN. See the lang attribute page.What is ARIA, and when should you use it?
ARIA attributes (
role,aria-label,aria-expanded,aria-live) tell assistive technology what a custom widget is and what state it is in. Use them only when no native element does the job.<!-- Good: native button, no ARIA needed --> <button>Save</button> <!-- ARIA describes state that HTML cannot express --> <button aria-expanded="false" aria-controls="menu">Menu</button>The trap: ARIA changes what is announced, never behavior.
role="button"does not make a div focusable or usable from the keyboard.What is the difference between
aria-label,aria-labelledbyandaria-describedby?aria-labelnames an element with a string,aria-labelledbytakes the name from other elements by id, andaria-describedbyadds a description read after the name.<button aria-label="Close dialog">×</button> <h2 id="billing">Billing address</h2> <section aria-labelledby="billing">...</section> <input id="pw" type="password" aria-describedby="pw-hint"> <p id="pw-hint">At least 12 characters.</p>aria-labelledbybeatsaria-label, which beats the native label. Put hints and errors inaria-describedbyso they are heard on focus.What do
tabindex="0",tabindex="-1"and a positivetabindexdo?tabindex="0"adds an element to the Tab order at its document position.tabindex="-1"makes it focusable from script (el.focus()) but not with Tab, which suits a heading you move focus to. A positive value jumps ahead of everything else.<div role="button" tabindex="0">Custom control</div> <h2 id="results" tabindex="-1">Results</h2> <!-- focused by script after a search -->Avoid positive values: the Tab order stops following the visual order.
What is a skip link, and how do you build one?
A skip link is the first link on the page and jumps to the main content, so keyboard users skip the header and menu. It is hidden until focused.
HTML<!DOCTYPE html> <style> .skip { position: absolute; left: -9999px; } .skip:focus { left: 8px; top: 8px; background: #fde68a; padding: 6px 10px; } nav { height: 220px; background: #f1f5f9; } </style> <a class="skip" href="#main">Skip to main content</a> <nav>Logo, menu, search, account links...</nav> <main id="main" tabindex="-1"> <h1>Main content</h1> </main>Click in the preview and press Shift+Tab to see it. Hide it off screen, not with
display: none, which takes it out of the Tab order.How do you announce dynamic changes to screen reader users?
Put the changing text in a live region:
aria-live="polite"waits for a pause,aria-live="assertive"interrupts.role="status"androle="alert"are the same two.HTML<!DOCTYPE html> <button id="save">Save</button> <p role="status" id="status"></p> <script> document.getElementById('save').onclick = () => { document.getElementById('status').textContent = 'Saved at ' + new Date().toLocaleTimeString(); }; </script>The trap: the region must be in the DOM before its text changes; an element inserted with the message already inside is often not announced.
How do you test a page for accessibility?
Combine automated checks with manual testing, because tools catch only part of the problems.
- Automated: Lighthouse or axe, also in CI.
- Keyboard: every control reachable with Tab, focus visible, no trap.
- Screen reader: NVDA, VoiceOver or TalkBack.
- Zoom and contrast: 200% zoom, text contrast at least 4.5:1, or 3:1 for large text (WCAG AA).
How do you make a data table accessible?
Use real table markup: a
<caption>that names the table,<th>for header cells withscope="col"orscope="row", and<thead>and<tbody>. A screen reader then announces each cell with its row and column headers instead of a stream of numbers.HTML<table> <caption>Test scores</caption> <thead> <tr><th scope="col">Student</th><th scope="col">Math</th><th scope="col">Science</th></tr> </thead> <tbody> <tr><th scope="row">Asha</th><td>92</td><td>88</td></tr> <tr><th scope="row">Ravi</th><td>79</td><td>95</td></tr> </tbody> </table>For headers that span several levels, link cells to them with
headersandid. Never use a table for layout. More in HTML tables.
HTML Accessibility Interview Questions
Labels, ARIA, keyboard support, focus and live regions, now standard in front end interviews.