On this page
Semantic HTML means choosing an element because of the role its content plays. The markup explains that something is navigation, a main heading, a self-contained article, or an action—not merely that it should look like a row or a box.
Browsers provide useful behavior and accessibility information for many native elements. Clear semantics also make source code easier for another developer to read. They are a strong foundation, but they do not repair unclear content, missing labels, poor contrast, broken focus behavior, or other accessibility problems by themselves.
Meaning comes before visual appearance
Imagine two pieces of text that both look like blue rounded rectangles. One takes a reader to another page. The other changes the current page.
They may share CSS, but their HTML should differ:
<a href="/notes/">Read learning notes</a> <button type="button">Mark as reviewed</button>
The link has a destination. The button represents an action. CSS can make either control look prominent, but appearance does not change its meaning or keyboard behavior.
This leads to a useful habit: first ask what the content is or does. Choose HTML from that answer. Style it afterward.
Page landmarks give the document broad regions
Landmarks are recognizable parts of a page, such as its main navigation and main content. Native HTML elements can expose these regions to browser accessibility APIs without adding a matching ARIA role by hand.
A common page structure looks like this:
<header>Site identity and introductory content</header>
<nav aria-label="Main navigation">Primary links</nav>
<main>The page's dominant content</main>
<footer>End-of-page information</footer>
Assistive technology can use landmarks and headings as navigation points. Sighted readers also benefit from a predictable visual and content structure.
Use <header> for introductory content
<header> can introduce the whole page or a section within it. A page header often contains the site name and navigation. An article header might contain its title and publication information.
It does not mean “the element that appears at the top because CSS put it there.” Its meaning comes from the content it introduces.
Use <nav> for important navigation
<nav> wraps a major set of links used to move through a site or document. Give it a concise accessible label when the label is not otherwise obvious, especially when a page contains more than one navigation region:
<nav aria-label="Main navigation">
<a href="#notes">Notes</a>
<a href="#about">About</a>
</nav>
Not every small collection of links needs <nav>. A sentence containing one related link can stay a paragraph.
Use <main> for the dominant content
<main> contains the content specific to the current page. Repeated site navigation and a repeated site footer usually sit outside it.
For an ordinary document, keep one visible main region. Give it an id if a skip link or in-page link needs a destination. In the example below, id="main-content" lets the site-name link move focus context toward the page content through normal fragment navigation.
Use <section> for a themed part of a page
<section> groups content that belongs to one theme or purpose when no more specific element fits. It should normally have a heading that describes that part of the document.
<section aria-labelledby="notes-title">
<h2 id="notes-title">Latest notes</h2>
<!-- Related notes belong here. -->
</section>
A section is not a replacement for every wrapper. If you need an element only to arrange two items in a grid, a <div> may communicate the honest amount of meaning: none beyond grouping.
Use <article> for self-contained content
An <article> represents a complete item that could make sense on its own or be reused elsewhere. A learning note, news story, forum post, or product card may qualify.
Two note entries can therefore be separate articles inside one section:
<section aria-labelledby="notes-title">
<h2 id="notes-title">Latest notes</h2>
<article>
<h3>HTML describes meaning</h3>
<p>A heading identifies a topic.</p>
</article>
<article>
<h3>CSS controls presentation</h3>
<p>A class can share a visual treatment.</p>
</article>
</section>
The <h3> headings sit below the section’s <h2> in the page hierarchy.
Use <footer> for closing information
A page-level <footer> can hold copyright text, legal links, or a short closing statement. An article can also have its own footer for information about that article.
As with <header>, the element is not defined by a fixed screen position. A sticky bar at the bottom is not automatically a semantic footer.
Choose a link for navigation and a button for an action
Use <a href="…"> when activating the control navigates to a real URL or fragment. Use descriptive link text that still makes sense when read out of context.
Use <button> when activating the control performs an action, such as saving a setting, opening a dialog, or changing the current document. Set type="button" for a general-purpose button so it does not unexpectedly submit a form if the markup is later moved inside one.
Do not create fake links with href="#" and JavaScript click handlers. Do not use a <div> with a click listener as a substitute for a button. Native controls already include semantics and keyboard behavior that a custom imitation would have to reproduce.
When <div> and <span> are appropriate
<div> and <span> are generic containers. They are useful when no element with a more specific meaning fits:
- Use
<div>to group block-level content for layout or scripting. - Use
<span>to target part of a line of text for styling or scripting.
Generic does not mean bad. A <div class="notes-grid"> is clearer than a <section> with no heading when the wrapper exists only to create a grid.
Build a complete semantic notes page
Create these two files:
semantic-notes/
├── index.html
└── script.js
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Learning notes</title>
</head>
<body>
<header>
<a href="#main-content">Learning Notes</a>
<nav aria-label="Main navigation">
<a href="#notes">Notes</a>
<a href="#about">About</a>
</nav>
</header>
<main id="main-content">
<section id="about" aria-labelledby="intro-title">
<h1 id="intro-title">Notes from this week's lessons</h1>
<p>Short explanations help me check what I understand.</p>
</section>
<section id="notes" aria-labelledby="notes-title">
<h2 id="notes-title">Latest notes</h2>
<article id="html-note">
<h3>HTML describes meaning</h3>
<p>A heading identifies a topic. A paragraph holds a complete thought.</p>
<a href="#css-note">Continue to the CSS note</a>
</article>
<article id="css-note">
<h3>CSS controls presentation</h3>
<p>Classes let several elements share the same visual treatment.</p>
<button id="review-note" type="button">Mark this note as reviewed</button>
<p id="review-status" aria-live="polite"></p>
</article>
</section>
</main>
<footer>
<p>Built as a small semantic HTML practice page.</p>
</footer>
<script src="script.js"></script>
</body>
</html>
const button = document.querySelector("#review-note");
const status = document.querySelector("#review-status");
button.addEventListener("click", () => {
status.textContent = "The CSS note is marked as reviewed.";
});
The CSS-note link navigates to a location, so it is an anchor. The review control changes the current page, so it is a button. The live-status paragraph gives the action a text result; the JavaScript uses textContent rather than inserting HTML.
How semantics help—and what they do not solve
Meaningful elements help browsers and assistive technologies expose page relationships. A screen-reader user may navigate by landmarks or headings instead of listening from the top. Reader modes and other tools may also use the structure.
Semantic HTML does not automatically make a page fully accessible. The page still needs clear labels and content, logical source order, keyboard-operable behavior, visible focus, sufficient contrast, useful error messages, appropriate alternative text for meaningful images, and testing with relevant tools and people.
Common overuse and misuse
Wrapping every block in <section>. Use a section for a themed, usually headed part of the document. Use a generic wrapper for layout-only grouping.
Putting every link inside <nav>. Reserve navigation landmarks for important collections of navigational links.
Using <article> for any card shape. Ask whether the content is a self-contained item. A purely decorative panel may be a <div>.
Using a link to trigger an action. If there is no meaningful destination, choose a button.
Using a button to go to another page. Navigation belongs in a real anchor with an href, so normal browser features such as copying and opening the destination still work.
Assuming semantics finish accessibility work. Test labels, focus order, zoom, contrast, and behavior too.
Practice
Practice: add a third note
Add another <article> under “Latest notes.” Give it an <h3>, a paragraph, and a descriptive
link to the first note. Then add a secondary navigation region in the footer and label it “Footer
navigation.” Inspect the accessibility tree and confirm that the two navigation regions have
distinct names.
What to learn next
The page now has meaningful elements and reusable class hooks. Next, learn how CSS selectors find those elements and how the cascade resolves competing styles. That will let you change presentation without weakening the document structure.