Learning objectives
- Tell presentational markup from semantic markup, and explain why HTML has carried both
- Recognize
div-itis andclass-itis in real markup, and cure them - Describe the accessibility tree, and how elements become roles and landmarks in it
- Choose among
header,footer,main,nav,aside,section,articleandsearch, and predict which landmark each one produces, if any - Refactor a
div-soup page into landmarks, and check the result in DevTools
Presentational and semantic markup
Lesson 01 split markup languages into two camps. Presentational markup says how something looks. Semantic markup says what something is. HTML has struggled with the split for most of its life, because it carried both kinds at once: font, big, small and b on one side, em, p, blockquote and h1 on the other. Each new version of the standard has tried to move appearance out to CSS and leave HTML with meaning.
The smallest example is a pair that looks identical in every browser. <b> was born as "bold." <strong> was born as "this matters." Both render heavy by default, so on screen they are indistinguishable. Now restyle them. Make strong red, and every important phrase on the site turns red, which is a sane result: the style follows the meaning. Make b red, and you have an element whose name says "bold" and whose look says "red," which is, as the slides put it, kind of crazy. HTML5 redefined b with a meaning of its own, and lesson 06 sorts out the text-level elements in detail. The point here is the habit of mind: pick the element for what the content is, and let CSS decide how it looks.
Even semantic elements carry a presentational bias in authors' heads. Ask a beginner what h1 does and the answer is usually "it makes text big." It does not. It says "this is the top-level heading," and the browser's default style sheet happens to make it big. A heading styled small is still a heading; a div styled big is still nothing.
Catching div-itis
Semantic markup sounds good, and the web mostly ignores it. The HTTP Archive's Web Almanac for 2024 counted the elements on millions of pages and found div "by far the most dominant element": 28.7% of all elements on mobile pages, more than links (12.6%) and span (11.2%) put together. Nearly one element in three on the web is a box that means nothing. The course calls this div-itis.
Think of div as the "um," "you know" or "something" of HTML as a spoken language. A sentence full of them can still get its point across to a patient listener who can see your hands. Take away the hands, and the listener is left with "um, something, you know." A page built from divs works the same way. A sighted user reads the layout and sees the header and the sidebar. A screen reader, a crawler or an AI agent gets only the tree, and in the tree every box is the same kind of box.
It does not matter, until it does: an accessibility audit fails, a crawler picks the wrong text as the content, a new developer reads six nested divs to find the sidebar. That is technical debt, and it compounds.
Here is a realistic case: a small blog page, built the way many templates still build pages. It looks fine.
The standard agrees
If a course's opinion is not enough, the HTML standard says the same thing in a note under the div element:
Authors are strongly encouraged to view the
divelement as an element of last resort, for when no other element is suitable. Use of more appropriate elements instead of thedivelement leads to better accessibility for readers and easier maintainability for authors.
Note the second benefit. Accessibility is about your users, and maintainability is about you. Even an author who somehow decided that users' needs were not their problem would still be paying the maintenance bill.
The cure
The cure is mostly vocabulary. Developers reach for div because it is the element they know will work, and the remedy is knowing the alternatives well enough that they come to mind first. When you are making a site header, use header. When you are making the navigation bar, use nav. When you are dividing the content into themed parts with headings, use section. When you are making a button, use button. Each of these is no more typing than the div it replaces, and each gives search engines and screen readers something to work with. The cure is also subtractive, which matters later: it removes markup rather than adding more.
Catching class-itis
class-itis is div-itis's companion. It takes three common forms. The first is long strings of presentational class names, a dozen to an element, each naming a look rather than a meaning:
The second is fake elements hiding in class values: <div class="button">, <div class="header">, <div class="aside">, written by authors who did not know, or did not trust, that the real element existed. The third is the class added "just in case," to a single element that could already be selected by what it is.
The standard has a note about this too, under the class attribute: "There are no additional restrictions on the tokens authors can use in the class attribute, but authors are encouraged to use values that describe the nature of the content, rather than values that describe the desired presentation of the content." A class named text-lg is a font element with extra steps. A class named button on a div is a button with none of a button's behavior: it cannot be focused with the keyboard, Enter and Space do nothing, it does not submit a form, and a screen reader does not announce it as a button. The fake search button on the div-soup page above has exactly these faults.
The cure
- Use the built-in element.
<button>, not<div class="button">;<nav>, not<div class="nav">. - Select by structure first. Write CSS rules for elements, built-in and custom, and for their place in the tree. Use a class to name a group that differs from the default, and an
idfor a fragment target or script hook, as lesson 03 explains. - Name what a thing is, not how it looks. If a class is still needed,
warningdescribes the content;red-boxdescribes one design that will change.
This is the course's house style, and the site you are reading follows it: almost no classes, and style sheets that select elements by what they are and where they sit. Some teams choose utility classes on purpose and accept the trade; it should be a choice, not a reflex.
Why semantics matter: the accessibility tree
Semantics stop being a matter of taste once you see where they go. From the DOM, the browser computes a second tree, the accessibility tree, and hands it to the operating system's accessibility interfaces. Screen readers, voice control, switch access and magnifiers all read that tree, not your source and not your pixels.
Each node in the accessibility tree carries a role (what kind of thing it is: link, button, heading, list, navigation), an accessible name (what it is called: the text of a button, the alt of an image, the label of a field), and its states (checked, expanded, disabled). The role comes from the element. <button> becomes a button, <nav> becomes navigation, <h2> becomes a heading at level 2. A div or span becomes the role generic, which assistive technology treats as nothing in particular, and many of them are dropped from the tree entirely. The rules that map each HTML element to a role are written down in a W3C specification, HTML Accessibility API Mappings, or HTML-AAM, and its companion for authors, ARIA in HTML.
A few roles mark out the large regions of a page. These are the landmark roles: banner, navigation, search, main, complementary, contentinfo, region and form. A screen reader can list a page's landmarks and jump straight to any one of them, the way a sighted user glances at the layout and looks straight at the sidebar. When you use semantic markup like header, footer, nav, main, headings, section and article correctly, you give assistive devices and search engines understood landmarks for the structure and meaning of your document. Use divs, and there are none.
The same structure lets reader modes, search engines and AI agents tell the content from the boilerplate around it. The Accessibility page follows the accessibility tree through the rest of the course.
The elements and the landmarks they make
Eight HTML elements can produce a landmark, and several of them do so only under conditions. The table gives the rule; the subsections give the reasoning.
| Element | Landmark role | Condition |
|---|---|---|
header | banner | Only when scoped to the body: not inside article, aside, main, nav or section |
footer | contentinfo | The same condition as header |
main | main | Always; one visible main per page |
nav | navigation | Always |
aside | complementary | Always when scoped to the body or main; inside article, aside, nav or section, only with an accessible name |
section | region | Only with an accessible name |
search | search | Always |
form | form | Only with an accessible name |
Four of these, article, aside, nav and section, are the standard's sectioning content, the category lesson 04 described as the one that "defines the scope of header and footer elements." The table shows what that scope does in practice.
header and footer
The standard defines header as "a group of introductory or navigational aids": usually a heading, often a logo, a search form, a table of contents. A footer is "a footer for its nearest ancestor sectioning content element, or for the body element if there is no such ancestor": who wrote it, related links, copyright. Neither is tied to a position on the screen; the standard notes that "footers don't necessarily have to appear at the end of a section, though they usually do."
Both can appear many times on a page, and that is where scope comes in. The page's own header, scoped to the body, becomes the banner landmark, the one region that says "the site around this page." A header inside an article is that article's header, the title and byline of one post, and it would be wrong to announce it as the site's banner. So it does not become one. HTML-AAM now maps it to a newer role, sectionheader, which is not a landmark, and allows browsers to expose nothing at all when it has no name and nothing else worth announcing. footer follows the same rule, with contentinfo for the page and sectionfooter for a section.
The rule looks only at those five elements. A header wrapped in a layout div directly inside the body is still the banner; Chrome exposes it as one. A header inside main is not, which is one more reason to keep the site header outside main.
main
main "represents the dominant contents of the document": what this page is about, as opposed to the header, navigation, sidebars and footer that repeat on every page of the site. It made official the <div id="main"> that most sites already had.
The rule is one visible main per page. The standard's exact wording: "a document must not have more than one main element that does not have the hidden attribute specified," which lets a single-page application keep several views in the document and show one at a time. It also must be hierarchically correct: its ancestors may only be html, body, div, a form without an accessible name, and autonomous custom elements. So main never goes inside article, aside, header, footer or nav. The validator enforces both rules. main is also the natural target of a skip link, covered in Usable links.
nav
nav is "a section of a page that links to other pages or to parts within the page," and it always produces the navigation landmark. That is exactly why it should be used sparingly. The standard says so directly: "Not all groups of links on a page need to be in a nav element — the element is primarily intended for sections that consist of major navigation blocks." Its own example is the short row of links in a footer, to the terms of service, the home page and a copyright page, for which "the footer element alone is sufficient."
The site's main menu is a nav; so is a table of contents for a long page, or a set of breadcrumbs. A list of tags under a post, three related links in a sidebar, or the social icons in a footer are not. If everything is a landmark, nothing is. When a page does have more than one nav, name each one, so the landmark list reads "Primary navigation, Breadcrumb navigation" rather than "navigation, navigation":
Leave the word "navigation" out of the name; the role already says it.
aside
aside holds "content that is tangentially related to the content around the aside element, and which could be considered separate from that content." Sidebars, pull quotes, a box of background facts, an advertisement, a group of secondary navigation blocks. The test is whether the surrounding content still reads correctly with the aside removed. The standard draws the line at parentheticals: "It's not appropriate to use the aside element just for parentheticals, since those are part of the main flow of the document."
A page-level aside, scoped to the body or to main, becomes the complementary landmark. Inside an article or section, HTML-AAM makes it a landmark only if it has a name, so that every pull quote in a long article does not crowd the landmark list. Browsers do not all follow that yet: Chrome 156, tested for this lesson, still exposes an unnamed aside inside an article as complementary. Name the asides you want found, and you get the same result everywhere.
section
section is "a generic section of a document or application," a thematic grouping of content, typically with a heading. The word that misleads people is "generic." The standard follows it at once with a warning:
The
sectionelement is not a generic container element. When an element is needed only for styling purposes or as a convenience for scripting, authors are encouraged to use thedivelement instead.
Its rule of thumb is that a section is appropriate "only if the element's contents would be listed explicitly in the document's outline": if it would have a heading in a table of contents, it is a section. A box that exists to get a background colour is a div.
An unnamed section has the generic role, the same as a div. Give it an accessible name, usually by pointing aria-labelledby at its heading, and it becomes a region landmark. Do that only for a section important enough that a user would want to jump to it from anywhere on the page. The sections of this lesson are unnamed on purpose: headings already let users move between them.
article
article is "a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication." The test is the RSS test: could this be lifted out and shown on its own, in a feed or on another site, and still make sense? A blog post passes; so do a news story, a product card, a forum reply and, in the standard's own list, "a user-submitted comment."
Articles nest. When they do, the standard says "the inner article elements represent articles that are in principle related to the contents of the outer article," which is exactly a post and its comments. article maps to the article role, which screen readers can announce and let users move between, but it is not a landmark. A chapter of a book is a section, since it leans on the chapters around it; a review of the book is an article.
search
search is the newest element in this lesson. It was added to the standard in 2023 and "represents a part of a document or application that contains a set of form controls or other content related to performing a search or filtering operation": a site search, a filter for a list of results, a global web search. It became Baseline in October 2023, when Chrome, Edge and Firefox 118 and Safari 17 all shipped it, and it has been Baseline widely available since April 2026.
Before it, the only way to mark a search was ARIA, <form role="search">, which still works. The standard adds that search is not for the results themselves, only for the controls that produce them.
form and address
A form becomes a form landmark only when it has an accessible name. HTML-AAM is explicit: "If a form has no accessible name, do not expose the element as a landmark." Most forms should stay unnamed. Name the one or two that a user would want to find directly, such as a checkout or a contact form, and leave the rest alone. The Forms section covers the form itself.
address is often guessed to be a landmark and is not. It "represents the contact information for its nearest article or body element ancestor," which makes it the right element for an author's or a site's contact details, usually in a footer, and the wrong element for postal addresses in general. HTML-AAM maps it to the group role.
div and span: the last resort
None of this makes div and span wrong. They are the generic block and inline containers, they map to the generic role, and they exist precisely for the cases where no element means what you need: a wrapper for a grid or flex layout, a hook for a script, a box that only exists to carry a background. A span around a few words to colour them, when the colour carries no meaning that em, strong or mark would express, is fine. So is the div that holds the landmark inspector in this lesson's demos, chosen because it adds nothing to the landmarks.
The danger is the other cases: the div standing in for a header, a sidebar or a button, with a class name doing the job of an element. Before HTML5 there was no aside, so authors wrote <div class="aside"> or whatever name they invented. Class names carry meaning only for readers who know the convention; elements are the shared vocabulary. A good habit before typing <div is to ask what the box is. If the answer is a noun from this lesson, use that element. If the answer is "a box," use the div.
The outline that never shipped
The sectioning elements once promised more. HTML5 described a document outline algorithm in which each section, article, aside and nav started a new level of the outline, so an h1 nested three sections deep would count as a third-level heading. Authors were told they could use h1 everywhere and let the nesting decide. The slides of the time already called the resulting outline "speculative," with good reason. As lesson 01 tells it, no browser ever exposed the levels it computed to assistive technology (only its default heading sizes shipped, as lesson 06 explains), and in 2022 the standard removed it.
The standard now says plainly: "The outline is all headings in a document, in tree order." Heading levels are what you write. An h1 inside a section is a level 1 heading, whatever wraps it. The sectioning elements still matter, for landmarks, for scoping header and footer, and for meaning, but the outline comes from h1 to h6 alone. Lesson 06 is about writing that outline well.
Moving by landmark
Screen-reader users rarely read a page from top to bottom. They skim, the way sighted users do, using keystrokes that jump to the next heading, link, list, form field or landmark. The keys differ from one screen reader to another, and from version to version, so treat these as examples rather than a reference: in NVDA, D moves to the next landmark and Shift+D to the previous one; in JAWS it is R (older versions used the semicolon); VoiceOver on macOS and iOS gathers landmarks into a list in its rotor. Each also offers a list of all the page's landmarks, named by role and accessible name.
On the semantic version of the demo page, that list reads roughly: banner, Primary navigation, search, main, Comments region, More from the journal complementary, content info. From any point on the page, the post's comments are two keystrokes away. On the div-soup version, the list is empty, and the only way to the comments is to move through the page element by element, or to guess at headings, of which the soup has only three, because its title is a div.
Screen readers differ in what they announce, too, and that is not something to design around. Write the right elements, check the tree in DevTools, and once in a while listen to your own page with the screen reader built into your operating system.
Fixing the problem we made? ARIA roles
There is another way to get landmarks onto a div-soup page: keep the soup and add ARIA. WAI-ARIA, Accessible Rich Internet Applications, defines a role attribute that sets an element's role directly, so <div role="navigation"> produces the same landmark as <nav>.
For many teams this is the preferred fix, because it is additive: nothing gets removed, more technology gets layered on top. It treats the symptom. The cure is subtractive: replace the div with the element and the role comes for free. The W3C's guide to using ARIA states this as its first rule:
If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
For landmarks the difference looks small, since a landmark role has no behavior to imitate. It still matters: the role lives in an attribute that is easy to drop in a refactor, CSS and scripts still have to select .nav-links, and the next developer still reads soup. For anything interactive the difference is large. <div role="button"> is announced as a button and does nothing else a button does: it needs a tabindex, a key handler for Enter and another for Space, and still will not submit a form.
Adding a role that the element already has, as in <nav role="navigation">, is harmless but noisy; ARIA in HTML lists it as allowed but "NOT RECOMMENDED." Roles earn their place where HTML cannot help, such as a legacy template you may not restructure. The aria-label and aria-labelledby attributes in this lesson are ARIA at its best: augmenting a correct element, not replacing one.
From div soup to landmarks
Back to the blog page. The refactor is a series of questions, one per box, and the answer to each comes from this lesson. Start with the soup's skeleton:
- The site header is the page's introductory and navigational aids, scoped to the body:
header, which gives thebanner. - The three links in it are the site's main navigation:
nav, named "Primary," with the links as aul, since they are a list. - The search box becomes
searcharound a realform; the fake button becomes abutton, and the input gets an accessible name. - The content wrapper holds what this page is about:
main. - The post is self-contained:
article. Its header becomes aheader, not a banner inside the article; the title becomes theh1, and the date atime. - The two parts of the post have headings:
section, left unnamed. - The tags line is information about the post: the article's
footer. It is a short row of links, so nonav. - The comments are a
sectionnamed by its heading, so it is a region a user can jump to, and each comment is anarticlenested in the post. - The sidebar is related but separate:
aside, insidemain, named by its newh2. - The site footer, scoped to the body, is the
footerand givescontentinfo. The contact line is the site's contact information, so it is anaddress.
The new version has no class attributes and a style sheet that reads like the page: body > header, nav ul, main > article > footer, article article for the comments. Without its inspector strip, it renders pixel for pixel the same as the soup, in light mode and dark, wide and narrow; that was checked with screenshots in Chrome. Everything that changed is invisible.
Try it: read the landmarks yourself
- Open landmarks-page.html in Chrome or Edge and open DevTools. In the Elements panel, open the Accessibility pane and turn on "Enable full-page accessibility tree"; the button that appears switches the Elements panel to the accessibility tree. Find the seven landmarks, and find the article's
header. What role does it have? - Do the same on div-soup.html. Find the Search "button." What role does the tree give it, and can the Tab key reach it?
- Predict, then check with the inspector: in a saved copy of the semantic page, move the page's
headerinsidemain. Then removearia-labelledbyfrom the commentssection. Then addaria-label="Archive"to an unnamedsection. Which landmarks appear and disappear each time? - List the landmarks of your own most recent project from its source. Is there one
main, with the site header outside it? - If you have a Mac, turn on VoiceOver (Command+F5), open the semantic page, and open the rotor (VO+U) to its landmarks list. On Windows, NVDA is a free download; press D to move from landmark to landmark. Then try the soup.
Summary
| Concept | Key points |
|---|---|
| Presentational and semantic | Presentational markup says how a thing looks; semantic markup says what it is. Choose the element for the meaning and let CSS decide the look. h1 means "top heading," not "big." |
div-itis | 28.7% of elements on mobile pages are divs (Web Almanac 2024). The standard calls div "an element of last resort." The cure is vocabulary, and it is subtractive. |
class-itis | Presentational class names, fake elements in classes, classes "just in case." Use the built-in element, select by structure first, and name classes for what content is. |
| Accessibility tree | Computed from the DOM; each node has a role, a name and states. HTML-AAM maps elements to roles. div and span are generic. |
| Landmarks | banner, navigation, search, main, complementary, contentinfo, plus region and form when named. Users list them and jump between them. |
header, footer | Banner and content info only when scoped to the body, outside article, aside, main, nav and section. Inside those, they belong to the section and are not landmarks. |
main | The dominant content. One visible per page; ancestors only html, body, div, unnamed form or custom elements. |
nav | Major navigation blocks only. Name each when there is more than one. |
aside | Tangential content. complementary at page level; inside sectioning content, only when named (Chrome still exposes it unnamed). |
section, article | A section is thematic, with a heading, and a region only when named; never a styling wrapper. An article is self-contained and syndicatable; articles nest, as comments in a post. |
search, form, address | search wraps search and filter controls; Baseline since 2023. A form is a landmark only with a name. address is contact information, role group, not a landmark. |
div and span | Still right for layout wrappers, script hooks and styling, when no element means what you need. |
| The outline | The sectioning outline algorithm never shipped and was removed in 2022. The outline is the headings, in tree order, at the levels you write. |
| ARIA roles | A band-aid for markup that cannot change. First rule of ARIA: use the native element. Redundant roles are not recommended. |
Next steps
Landmarks divide a page into its large regions. Inside them, the finer structure comes from headings, paragraphs, lists and the text-level elements, and the outline a screen-reader user scans is made of headings alone. Lesson 06, Headings, text and lists, takes that structure down to the word, including the b and strong question this lesson only opened. For the skip link that pairs with main, see Usable links; for how CSS can select all this structure without classes, see Selectors.
