Semantic HTML
Date: 2026-08-16
Choosing elements for what they mean rather than how they look. The meaning is what accessibility, keyboard behaviour, form submission and search all derive from — so a
divwith a click handler isn’t a styling choice, it’s a decision to reimplement six things badly.
What it is
Semantic HTML is using the element whose defined meaning matches the content’s role — <button> for something that performs an action, <nav> for navigation, <h1>–<h6> for a document outline.
The browser reads that meaning and supplies behaviour from it. Nothing else in the platform gives you so much for so little.
What a native element hands you
Compare a real button with a styled div:
<button type="submit">Add to basket</button><div class="btn" onclick="addToBasket()">Add to basket</div>The second is missing all of this, and each item is a separate bug:
Free with <button> | Missing from the div |
|---|---|
| Focusable in tab order | Needs tabindex="0" |
| Fires on Enter and Space | Needs a keydown handler for both |
| Announced as “button” by screen readers | Announced as nothing — The Accessibility Tree |
| Disabled state that blocks interaction | disabled does nothing on a div |
| Submits the enclosing form | Manual |
| Focus ring by default | Needs styling |
| Recognised as an action by automation and translation tools | Not |
In plain terms: reaching for a div means signing up to rebuild keyboard support, focus, and screen reader semantics by hand, forever, on every element. The native element already passed those tests.
The elements that carry the most
Not the full list — the ones where the choice actually changes behaviour:
<button>vs<a>— the single most common error.<a href>navigates;<button>acts. An anchor with nohrefis not focusable; a button used for navigation breaks open-in-new-tab and middle-click<form>— submission, validation, Enter-to-submit, autofill grouping. See Forms- Headings —
<h1>–<h6>form the document outline screen reader users navigate by. Skipping levels for visual size is the most common accessibility failure on retail sites; use CSS for size <label for>— clicking the label focuses the field and the field gets an accessible name. Wrapping withoutforalso works; a nearby<span>does not<table>for tabular data, with<th scope>. For layout, never<ul>/<ol>— screen readers announce the item count, which is genuine navigational information- Landmarks —
<main>,<nav>,<header>,<footer>,<aside>. Assistive technology jumps between them; without them the page is one undifferentiated block
Where it pays off commercially
- Accessibility is the largest one, and in the UK it’s a legal exposure as well as an ethical one — see Accessibility Law in the UK
- Forms convert better when autofill works, and autofill depends on correct
type,nameandautocompleteattributes - Search engines derive structure from headings and landmarks — Technical SEO
- Mobile keyboards change with input type.
type="email"andtype="tel"produce the right keyboard;type="text"produces friction on every field
The trap: semantics you can’t see
Because none of this is visible, a page can look perfect and be structurally broken, and nothing fails loudly. The two checks worth building into a review:
- Tab through the page. Everything interactive should be reachable, in a sensible order, with a visible focus indicator — Keyboard Navigation
- Read the heading outline. In DevTools’ accessibility panel or via an extension. If it doesn’t read like a table of contents, the structure is wrong
ARIA is the fallback, not the tool
The first rule of ARIA — Accessible Rich Internet Applications — is not to use it if a native element will do. role="button" on a div tells assistive technology it’s a button while supplying none of the behaviour, which produces something that announces correctly and doesn’t work. That’s worse than the unlabelled div, because it promises something it can’t deliver.
ARIA earns its place for genuinely custom widgets the platform has no element for — comboboxes, tab panels, live regions. See ARIA.