Semantic Markup

Method

Writing markup with the tag that matches what each element means, so the structure of a screen is visible in the code that assistive technology reads.

Why it exists

For a long stretch, turning a design into code was understood as a job of matching appearance. HTML, the language a web screen is built from, has tags with fixed meanings, but ignoring them and building everything out of generic container tags was easier. Containers take any styling you give them, and on screen the result looked the same.

Where it wasn't the same was anywhere that doesn't look at the screen. A screen reader, which speaks what's on the page aloud, reads the meaning written in the code. Something built as a container is announced as a container no matter how much it resembles a button, and a row of items styled to look like a list never tells the listener how many items there are.

At Pagedeck the gap showed up in the share buttons. Noa's design had three icon buttons in a row, and Theo built them as containers because styling them that way was simpler. On screen it matched the design. But pressing tab through the page skipped all three, and a screen reader never mentioned that buttons existed. The item came back as a finding in a public-sector customer's accessibility review.

Semantic markup closes that gap. Build the thing you press as a button tag and both the announcement and the interaction come along with it.

How to run it

Start by dividing the screen by meaning rather than by appearance. Five steps.

  1. Mark out the regions. Header, navigation, main content, complementary content and footer each have a designated tag. Set up that way, a screen reader user can jump past the menu straight into the body instead of hearing the same forty navigation links on every page.
  2. Stack headings by level. One top-level heading per screen, then descend one step at a time. Don't skip a level to get smaller text — size comes from styling, level comes from meaning. Screen readers pull headings out to skim a document, so a broken sequence reads like a book with a shuffled table of contents.
  3. Build interactive elements with their own tags. A button if it does something here, a link if it takes you somewhere else. A button tag brings tab selection and enter activation with it for free under keyboard navigation. Bolt a click handler onto a container and you rebuild both by hand.
  4. Use real list and table tags. A list tag carries the fact that there are five items, and marking the header row of a table means each cell gets announced with the column it belongs to — "Status: failed" rather than just "failed".
  5. Add attributes only for what tags can't express. Whether a custom dropdown is currently open is that kind of state, and ARIA is what you use for it. Nothing that a tag already handles belongs here.

Three checks confirm the work. Put the mouse away and reach every function with tab, listen to the page through a screen reader, and pull out just the headings to see whether they read as an outline.

When it fits and when it doesn't

It fits almost any screen, and pays most on document-like and form-heavy ones. Building it this way from the start costs close to nothing — picking a meaningful tag instead of a container is the same amount of work. Retrofitting is expensive, because styling tends to be attached to tag names, so changing a tag disturbs the layout.

The limits are clear enough. Four of them matter.

  1. Markup alone doesn't finish accessibility. Alt text that describes images, a visible focus ring showing the current position, and the contrast between text and background are all separate work.
  2. Some things have no standard tag. Tab groups, autocomplete lists and other custom widgets have no equivalent, which is where ARIA gets used.
  3. Correct tags can still be in the wrong order. Content is announced in code order, so an element styled into a position near the top while sitting near the bottom of the source gets heard out of sequence. A sidebar that visually sits beside the article but comes after it in the source gets read last, which is usually fine, and the reverse case usually is not.
  4. Automated checkers can't catch everything. Of the WCAG criteria, which sort requirements into levels, roughly half can be judged by a machine; the rest needs a person listening.

Search gets something out of it too. Search engines also read heading levels and region boundaries to work out structure, so this runs in the same direction as on-page SEO.

How it sounds at work

"This button is a container. Can you make it a button tag?"

So it gets tab focus and is announced as a button.

"Heading levels jump from 1 to 4 here. Let's handle the size with styling."

Don't break the structure to get a font size.

"A tag covers this case, so no ARIA needed."

Reach for the standard tag before reaching for attributes.

Pagedeck changed its handoff order after that review finding. When Noa passes a design over, she notes what each element is: this is a button, this is a link, this group is a list. Theo picks tags from those notes, and styling comes after. Neither of them treats it as a review step, because catching it in the design handoff costs a sentence and catching it after launch costs a rewrite.

What went down afterward wasn't only the accessibility findings. Support requests from people filling out forms with a keyboard dropped, and reusing the same component on another screen took less editing. When a tag carries the meaning, the element behaves the same wherever it's placed.

What people get wrong

The most common reading is that this is a search ranking technique. Explanations of it usually mention that search engines read structure, so it sounds that way. But it's a device for conveying content accurately, not for raising a position. Tidying tags doesn't move rankings. Aim at rankings instead and you drift toward inserting heading tags regardless of meaning, which makes a screen reader announce a document with twenty headings and costs you the thing you were after in the first place.

The other belief is that a container plus attributes is equivalent. ARIA lets you declare a role of button, so the outcome looks identical. In practice only the name transfers; the behavior doesn't. Tab focus, activation with enter and space, and announcing a disabled state all have to be rebuilt by hand, and missing any one of them leaves a button that is announced but can't be pressed. That's why the first rule of ARIA says not to use ARIA where a tag will do — the attribute describes the element, while the tag also makes it work.

Where to go next

  • Accessibility

    see how standards, implementation and assistive technology interlock

  • Alt text

    the place for information no tag can carry

  • HTML

    check which language these tags belong to

Related terms

Last updated 2026-09-16