Semantic HTML and Landmarks
TL;DR
Semantic HTML is ~80% of accessibility for free. Native elements (<button>, <a>, <nav>, <main>, <h1>–<h6>, <label>, <table>) come with the correct role, keyboard behavior, focusability, and states that assistive tech relies on. A <div onClick> has none of that. Use the right element first; reach for ARIA only to fill genuine gaps. Landmarks (header, nav, main, aside, footer) let screen-reader users jump between page regions; a logical heading hierarchy is how they skim.
Interview Q&A
Q: Why prefer <button> over <div onClick>?
A: A native <button> is, for free:
- focusable (in the tab order) — a
<div>is not withouttabindex="0", - operable by keyboard — Enter/Space activate it; a
<div>needs manualkeydownhandling, - announced as “button” with its label by screen readers — a
<div>is announced as nothing, - equipped with disabled semantics and form participation.
To match a <button> with a <div> you’d need role="button", tabindex="0", and key handlers for Enter and Space — and you’d still miss edge cases. Just use <button>.
Q: What are landmarks and why do they matter?
A: Landmark elements define page regions that screen-reader users navigate between directly (e.g., “jump to main”):
| Element | Role | Purpose |
|---|---|---|
<header> |
banner (when top-level) |
site header |
<nav> |
navigation |
navigation blocks |
<main> |
main |
the primary content (one per page) |
<aside> |
complementary |
tangential content |
<footer> |
contentinfo (top-level) |
site footer |
<section> with a name |
region |
named significant area |
<form> with a name |
form |
a form region |
Use one <main>. Give repeated landmarks accessible names (<nav aria-label="Primary">, <nav aria-label="Footer">) so users can tell them apart.
Q: How should headings be structured?
A: One <h1> describing the page, then a logical, non-skipping hierarchy (h1 → h2 → h3, don’t jump h2→h4). Headings are the screen-reader equivalent of skimming — users list and jump by heading. Don’t pick a heading level for its font size (style with CSS); pick it for document structure.
Q: When is a <div>/<span> the right choice?
A: For styling/layout containers with no semantic meaning. <div> and <span> have no implicit role, which is correct when the element is purely presentational. Problems arise only when you put behavior (click handlers, “buttons,” “links”) on them.
Q: What semantic elements are commonly under-used?
A: <button type="button"> (vs div), <a href> for navigation (vs button/div with JS), <label> tied to inputs, <fieldset>/<legend> for groups, <table> with <th scope> for tabular data, <ul>/<ol>/<li> for lists, <nav>/<main>/<aside>, <details>/<summary> for native disclosure, <dialog> for modals, <time>, <figure>/<figcaption>. Each carries semantics ARIA would otherwise have to fake.
Q: <button> vs <a> — when each?
A: <a href> navigates (changes URL / location) and should be a link. <button> performs an action in place (submit, toggle, open menu). Misusing them breaks expectations: links open in new tabs, are bookmarkable, and respond to Enter; buttons respond to Enter and Space and aren’t navigable destinations. A “link” with role="button" is usually a sign you picked the wrong element.
Gotchas / edge cases
tabindex> 0 is an anti-pattern — it jumps the element ahead of natural order and creates confusing focus. Use0(in natural order) or-1(focusable only programmatically).role="presentation"/aria-hiddenon interactive elements removes them from the a11y tree but they remain keyboard-focusable — a trap. Don’t hide focusable things.- Headings used for size produce nonsense outlines for screen readers — keep level = structure, size = CSS.
- Multiple
<main>or<h1>confuses landmark/heading navigation. - Generic link text (“click here”, “read more” ×10) is useless out of context — screen-reader users list links; make them self-describing.
<section>without an accessible name is not exposed as a landmark — name it or use a plain element.
What a senior is expected to say
- “Semantic HTML gives role, keyboard behavior, focusability, and state for free —
<div onClick>gives none. Right element first, ARIA only for gaps.” - “Landmarks let screen-reader users jump between regions; one
<main>, named duplicate<nav>s.” - “Headings are document structure for skimming — level by meaning, size by CSS, no skipped levels.”
- “
<a>navigates,<button>acts; positivetabindexis an anti-pattern.”
Cross-references
- ARIA for the genuine gaps: 03_aria.md
- Keyboard & focus behavior you get free with semantic elements: 04_keyboard_and_focus.md
- WCAG 1.3.1 (info & relationships): 01_wcag_and_pour.md
- HTML element reference / primer: ../01_html/
Further reading
- MDN — HTML: A good basis for accessibility: https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML
- ARIA Landmarks (W3C WAI): https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/
- HTML spec — Sections: https://html.spec.whatwg.org/multipage/sections.html