01 — Purpose

Review the contract first

Markup is the contract with browsers, assistive tech, and the next developer — get it right before styles and scripts pile on.

Use this checklist on HTML changes in pull requests — templates, components, and partials. Pair it with the CSS and JavaScript code review checklists when a feature touches all three. See HTML standards for the full rationale.

02 — Semantics

Semantics and controls

Choose elements for what they are, not what you want them to look like.

  • the right semantic element for each control, region, and list
  • buttons for actions on the page — links for navigation and real URLs
  • no href="#" or div click handlers standing in for buttons or links
  • details / summary, dialog, or native patterns considered before custom widgets
  • landmarks used sensibly — header, main, nav, footer where they describe the page

03 — Structure

Headings and document structure

Headings are navigation for everyone — not styling hooks with level skips.

  • one logical h1 per page or view — topic matches the page purpose
  • heading levels do not skip for visual reasons — hierarchy reflects outline, not CSS
  • lists use ul, ol, or dl — not paragraphs with manual bullets
  • skip link to main present on full page templates
  • page still makes sense with stylesheets disabled — structure carries meaning

04 — Forms

Forms and inputs

Bad form markup creates support tickets that look like JavaScript bugs.

  • every control has an associated visible label — placeholder is not a label
  • related inputs grouped in fieldset with legend where it helps
  • correct input types and autocomplete where browsers can help
  • required fields marked in HTML — not only with asterisks in CSS
  • submit uses button type="submit" — not a link pretending to submit
  • error messages associated with fields — aria-describedby or native validation where appropriate

05 — Data

Tables, images, and media

Tables and images are semantic too — misuse them and you pay in accessibility and SEO.

  • tables used only for tabular data — with th, scope, and captions where needed
  • meaningful images have accurate alt — decorative images use alt=""
  • icons paired with visible text or accessible name — not icon-only controls without labels
  • video and audio have captions or transcripts when content matters
  • iframes have a descriptive title and are justified

06 — Accessibility

ARIA and accessibility in markup

Native HTML first — ARIA is for gaps, not shortcuts.

  • ARIA only where native HTML cannot express the behaviour
  • no redundant ARIA that fights the underlying element — e.g. role="button" on a real button
  • expanded/collapsed, selected, and disabled states reflected in attributes when custom widgets are unavoidable
  • live regions used sparingly for meaningful dynamic updates — not every re-render
  • accessibility QA checklist flagged if user-facing behaviour changed

07 — Sign-off

Before you approve

When in doubt: is this the simplest HTML that correctly describes what this is?

  • core tasks achievable without JavaScript — enhancement is optional, not mandatory
  • no copy-pasted markup blocks that should be a shared partial or component
  • invalid or deprecated elements avoided — validate mentally or with a linter where you have one
  • frontend QA checklist considered when this ships to users, not only when merged