Frontend Syntax HTML5 Semantic
This skill fixes the choice of HTML element for every region and content type. It is built on the architecture position from [[frontend-core-architecture]]: the markup layer is the foundation, and native semantic elements ALWAYS beat <div role="..."> for accessibility tree mapping, focus management, and platform integration.
The skill targets evergreen-2026 browsers. The <search> element (Baseline Widely Available since October 2023) and <details name=""> accordion mutual exclusion (Baseline 2024) are treated as available without polyfill. Declarative Shadow DOM via <template shadowrootmode> is Baseline becoming Widely Available.
Quick Reference
Landmark elements and implicit ARIA roles
| Element | Implicit role | Cardinality per page | Purpose |
|---|---|---|---|
<header> |
banner when child of <body>, generic elsewhere |
one banner per document | Top-of-page identification (logo, site name, primary navigation slot) |
<nav> |
navigation |
multiple allowed if each is labelled | Block of navigation links |
<main> |
main |
exactly one per document | Primary content unique to the page |
<aside> |
complementary |
multiple allowed | Tangentially related content (call-outs, sidebars) |
<footer> |
contentinfo when child of <body>, generic elsewhere |
one contentinfo per document | Bottom-of-page info (copyright, secondary links) |
<article> |
article |
multiple allowed | Self-contained, syndicatable item (blog post, comment, card) |
<section> |
region only when given an accessible name |
multiple allowed | Thematic grouping with a heading |
<search> |
search |
typically one per page | Container for the controls that PERFORM a search (not the results) |
<figure> |
figure |
multiple allowed | Self-contained content (image, code block, diagram) plus optional caption |
<details> |
group (with <summary> as button) |
multiple allowed | Native disclosure widget |
<dialog> |
dialog or alertdialog per usage |
multiple allowed | Modal or non-modal dialog; full mechanics in [[frontend-impl-popover-dialog-anchor]] |
Verified against MDN: <search> (verified 2026-05-19), MDN: <details> (verified 2026-05-19), MDN: <template> (verified 2026-05-19), and WHATWG HTML Living Standard, Sections (verified 2026-05-19).
The native-first rule
| Need | Native element | Do NOT do |
|---|---|---|
| Navigation region | <nav> |
<div role="navigation"> |
| Search controls region | <search> |
<form role="search"> |
| Banner region | <header> (direct child of <body>) |
<div role="banner"> |
| Page contentinfo | <footer> (direct child of <body>) |
<div role="contentinfo"> |
| Main region | <main> |
<div role="main"> |
| Aside / complementary | <aside> |
<div role="complementary"> |
| Disclosure | <details> + <summary> |
<button> + manual aria-expanded plumbing |
| Modal | <dialog> + showModal() |
<div role="dialog"> |
Native elements get correct focus order, correct keyboard interaction, correct accessibility tree mapping, and correct platform integration for free. The full Authoring Practices comparison lives in [[frontend-a11y-aria-patterns]].
Decision Trees
Decision: which landmark element fits this region?
Top-of-page identification (site name, logo, primary navigation slot)
-> <header> (one banner per document, direct child of <body>)
Block of navigation links
-> <nav>
If multiple <nav> on one page, give each an aria-label or aria-labelledby
Primary content, unique to this page
-> <main> (EXACTLY one per document)
Tangentially related content (call-outs, related-posts, ads)
-> <aside>
Bottom-of-page info (copyright, secondary links)
-> <footer> (one contentinfo per document, direct child of <body>)
Self-contained, syndicatable item (a blog post, a comment, a product card)
-> <article>
Thematic grouping that needs a heading
-> <section> with an h2..h6 inside
If no heading is appropriate -> use <div> instead
Search controls (the input + submit, NOT the results listing)
-> <search>
Use ONLY for the form that performs the search.
NEVER wrap the results listing in <search>.
Self-contained content (image, code, diagram) with optional caption
-> <figure> + optional <figcaption>
Disclosure (collapsible region)
-> <details> + <summary>
For accordion mutual-exclusion: give all sibling <details> the same name attribute.
Decision: do I need role="..." ?
Is there a native HTML element with the right semantics?
yes -> use the element. NEVER add a role; it duplicates or conflicts with the implicit role.
no -> continue
Is the requirement a custom interactive widget (e.g. combobox, tablist, tree, treegrid) that no HTML element implements natively?
yes -> use ARIA. See [[frontend-a11y-aria-patterns]] for the WAI APG patterns and required keyboard and state plumbing.
no -> question your requirement; you probably need a native element you have not considered yet.
The First Rule of ARIA: do not use ARIA if a native element with the required semantics exists. The Second Rule of ARIA: do not change native semantics unless absolutely necessary.
Decision: <article> vs <section> vs <div>
Could this content be syndicated, repeated in a feed, or pulled out as a standalone item?
yes -> <article>
no -> continue
Does this region have a heading and represent a thematic grouping of content?
yes -> <section> (with a heading inside, h2..h6)
no -> continue
Is this region purely a styling or scripting wrapper with no semantic meaning?
yes -> <div>
no -> reconsider; one of the above probably applies.
A <section> without a heading is meaningless to assistive technology. ALWAYS pair <section> with a heading element. NEVER use <section> as a generic styling wrapper.
Patterns
Pattern: the landmark skeleton
ALWAYS structure a document with the canonical landmark skeleton:
<body>
<header>
<a href="/" class="logo">Brand</a>
<nav aria-label="Primary">
<ul><li><a href="/products">Products</a></li></ul>
</nav>
<search>
<form role="search-form-only-if-needed" action="/search">
<label>Search <input type="search" name="q"></label>
<button>Search</button>
</form>
</search>
</header>
<main>
<h1>Page title</h1>
</main>
<aside aria-label="Related">
</aside>
<footer>
</footer>
</body>
Note that <search> wraps the controls that perform the search, NOT the results. The implicit role search on <search> replaces the legacy <form role="search"> pattern; do NOT add role="search" to the inner <form>.
Pattern: the <search> element
Source: MDN: <search> (verified 2026-05-19).
The <search> element groups one or more search-related controls (input, button, filters). It has implicit ARIA role search. Baseline Widely Available since October 2023.
Authoring rules:
- ALWAYS wrap the search controls in
<search>. NEVER wrap the results listing in<search>. <search>MAY contain a<form>inside it; the inner form does NOT needrole="search"because the outer<search>already provides the landmark.- The element is purely semantic. It has NO default visual styling and NO interactive behavior of its own.
- Multiple
<search>regions on a single page are allowed (e.g. site search and a filter panel); label each witharia-labelif more than one is present.
Pattern: <details> and the accordion via name
Source: MDN: <details> (verified 2026-05-19).
The <details> element is the native disclosure widget. Its first child MUST be <summary>, which becomes the toggle button.
<details>
<summary>How do I install?</summary>
<p>Run the install script.</p>
</details>
Accordion-style mutual exclusion (Baseline 2024) uses the shared name attribute. All <details> with the same name form an exclusive group: opening one closes the others.
<details name="faq"><summary>Q1</summary>A1</details>
<details name="faq"><summary>Q2</summary>A2</details>
<details name="faq"><summary>Q3</summary>A3</details>
The toggle event fires on open and on close. The element exposes the open boolean attribute; toggling it programmatically opens or closes the disclosure.
NEVER rebuild this widget with <button aria-expanded> plumbing when <details> fits the requirement.
Pattern: <dialog> light reference
Source: MDN: <dialog> (verified 2026-05-19).
<dialog> is the native modal-or-non-modal dialog element. Per MDN: tabindex MUST NEVER be set on <dialog>. Initial focus goes to the first focusable descendant unless autofocus is set on a specific descendant. Full mechanics (showModal(), show(), close(), closedby, ::backdrop, top-layer behavior) belong in [[frontend-impl-popover-dialog-anchor]].
For this skill the essential rules:
- NEVER add
tabindexto a<dialog>. - ALWAYS use
<dialog>for modal patterns; do NOT roll your own<div role="dialog">. - Implicit role is
dialogwhen opened viashow(), and effectivelydialogwhen opened viashowModal(). Userole="alertdialog"only for interrupt-style dialogs that demand immediate user response.
Pattern: declarative Shadow DOM via <template shadowrootmode>
Source: MDN: <template> (verified 2026-05-19).
Declarative Shadow DOM lets the HTML parser attach a shadow root at parse time, with no JavaScript on the critical path. Three attributes control behavior:
| Attribute | Values | Effect |
|---|---|---|
shadowrootmode |
open or closed |
Required. Marks the <template> as a shadow root payload. open allows script access via element.shadowRoot; closed does not. |
shadowrootdelegatesfocus |
boolean | When the host receives focus, focus is delegated to the first focusable descendant inside the shadow root. |
shadowrootclonable |
boolean | The shadow root is cloned when the host element is cloned (e.g. by cloneNode(true)). |
<my-card>
<template shadowrootmode="open" shadowrootdelegatesfocus>
<style>
:host { display: block; padding: 1rem; border: 1px solid currentColor; }
</style>
<slot></slot>
</template>
Card content goes here in light DOM.
</my-card>
Declarative Shadow DOM enables server-rendered web components that hydrate without any JavaScript dependency for first paint. The full custom-element registration model lives in [[frontend-impl-web-components]].
Pattern: document outline and heading hierarchy
The HTML5 document outline is derived from heading elements (<h1> through <h6>), NOT from sectioning elements. ALWAYS write headings in document order; NEVER skip levels for visual reasons.
Rules:
- ONE
<h1>per document (the page title). Authors MAY repeat<h1>per<article>if the article is rendered standalone in feeds, but a single page-level<h1>is the safe default. - ALWAYS place an
<h2>(or lower) inside each<section>and<article>. A<section>without a heading does not contribute a region to assistive technology and reads as meaningless. - NEVER skip a level. After
<h2>the next sectioning heading is<h3>, never<h4>.
For grouping a heading with a tagline or subtitle, use <hgroup> with one heading plus paragraph children.
Pattern: when an element accepts the implicit role for free
Sectioning elements behave differently based on context:
<header>has rolebannerONLY when it is a direct child of<body>(or of an element whose role ismainper some implementations). Inside an<article>or<section>,<header>is generic.<footer>has rolecontentinfoONLY when it is a direct child of<body>. Inside an<article>,<footer>is generic.<section>has roleregionONLY when it has an accessible name (aria-label,aria-labelledby, ortitle). Without a name,<section>is a generic element with no landmark role.
NEVER assume a sectioning element always exposes a landmark. ALWAYS verify with an accessibility tree inspector (Chrome DevTools, Firefox Accessibility Inspector, axe-core).
Cross-references
[[frontend-core-architecture]]for why the markup layer is the foundation and how native semantics map to the accessibility tree.[[frontend-syntax-html5-form]]for the form-control surface (<input>,<select>,<textarea>, Constraint Validation API).[[frontend-impl-popover-dialog-anchor]]for full<dialog>and Popover API mechanics, anchor positioning, and theclosedbyattribute.[[frontend-impl-web-components]]for custom-element registration that consumes declarative Shadow DOM.[[frontend-a11y-aria-patterns]]for when a custom widget genuinely requires ARIA.[[frontend-a11y-focus-keyboard-inert]]for focus management and theinertattribute.
Reference Links
- WHATWG HTML Living Standard: Sections (verified 2026-05-19)
- MDN:
<search>(verified 2026-05-19) - MDN:
<details>(verified 2026-05-19) - MDN:
<dialog>(verified 2026-05-19) - MDN:
<template>(verified 2026-05-19)
Reference files local to this skill:
references/methods.md: complete landmark element matrix with implicit ARIA role per context, attribute surface for<details>,<dialog>and<template>, document outline algorithm summary.references/examples.md: framework-agnostic code examples including a full landmarked HTML page suitable for an axe-core landmarks audit.references/anti-patterns.md: six anti-patterns with symptom, root cause, and fix.