Definition: Semantic HTML means choosing each element for what it means, not how it looks: <button> for actions, <a href> for destinations, <nav> for navigation, <h2> for a heading. The browser turns that meaning into roles that screen readers announce, and supplies the right keyboard behaviour for free [1][2].
German: Semantisches HTML · Also: semantic markup · Last reviewed: 27 September 2026
Why meaning matters more than appearance
With CSS, a <div> can look like a button, a heading or a list. In the accessibility tree it remains a <div> with no role [4]. A real element, on the other hand, brings a lot with it without a single extra line of code [2]:
- A
<button>is reachable with Tab, responds to Enter and Space, and is announced as a "button". - An
<a href>is reachable, responds to Enter and appears in the screen reader's list of links. - A
<label for>ties text to a field; clicking the text puts focus in the field. - A
<ul>is announced as "list, 5 items". <th>turns table headers into headings for every cell.
That is exactly what WCAG 1.3.1 Info and Relationships requires: structure you can see must also be in the code [3].
The right element for the job
| Job | Right element | Common stand-in |
|---|---|---|
| Trigger an action | <button> | <div onclick> |
| Go to a page | <a href> | <span onclick> |
| Main content | <main> | <div id="main"> |
| Heading | <h2> | <p class="title"> |
| List | <ul>, <ol> | paragraphs with dashes |
| Data table | <table>, <th> | a grid of <div>s |
| Label a field | <label> | a placeholder only |
In code
<!-- Looks like a button, isn't one -->
<div class="btn" onclick="save()">
Save
</div>
<!-- Semantic: Tab, Enter and Space work -->
<button type="button" onclick="save()">
Save
</button>
Common mistakes
- Headings chosen by font size: the level follows the outline; CSS handles the size. See heading structure.
- Links and buttons mixed up: a link goes somewhere, a button does something. An
<a>withouthrefcannot even be reached with Tab. - Tables for layout, or the reverse: data tables built from
<div>s. <br>and empty paragraphs for spacing. Screen readers announce some of them as "blank".- Everything in
<div>s, then ARIA on top. That is more work and more fragile than using the right element – see ARIA.
How Reviseberg handles it
axe-core finds many consequences of missing semantics: lists without valid items (list, listitem), fields with no label (label), a skipped heading level (heading-order) or a page with no main region (landmark-one-main). Lists and labels map to WCAG criteria (1.3.1, 4.1.2). Heading order and the main region are best practice in axe-core, so Reviseberg shows them as "best practice, no WCAG criterion" and never counts them as a failed criterion. The keyboard agent reports keyboard:unreachable when an element has an onclick attribute or a control role but cannot be reached with Tab – the classic <div> posing as a button. Handlers attached with JavaScript are invisible to any check from outside. And whether the structure in the code matches the visible layout is, in the end, for a person to decide.
Related terms
Accessibility tree · ARIA · Landmark · Heading structure · Keyboard accessibility