ID: I202602281545
Status: idea
Tags: web development, HTML

semantic elements

There are a ton of semantic elements. Semantic elements are elements that have meaning and intent to them. Whilst you are able to make a website with only div, it is probably better to use a header or footer or other elements with meaning. This makes your website more understandable to things like screen readers.

What are Semantic Elements?

A semantic element clearly describes its meaning to both the browser and the developer. Examples of non-semantic elements: <div> and <span> - Tells nothing about its content. Examples of semantic elements: <img>, <table>, and <article> - Clearly defines its content

Some semantic elements have base styling applied to them. Semantic elements also already convey ARIA roles by default, but developers are able to overwrite these, just like the default styling.

How to use them

There are general logical rules for the semantics. You can see it on the image above. That being said, it is also a thing where you have to choose on “what feels right” in some cases, this is because there are no strict rules, and sometimes semantics overlap or it is a gray area.

In this section I will only go into the main semantics.

Main semantic rules

The Main

The <main> is used for the entire part of the page that the user expects to find. In a blog example, it would include the entire blog and everything related to it, but it would exclude the header and footer for the page, it excludes the <aside> sidebar for navigation, and it excludes things like Ads.

The Article

The article is the content that the users are visiting your page for. If you are a blog it’ll be the entire blog article and not the header, footer, aside or ads. And yes this sounds like the Article is the same as the Main, but they are different. Think of it this way, if your article is moved to someone else their site, it should take all the relevant information with it. But this would exclude some “other relevant blogs” section that might be in your main, but shouldn’t be in your article. This line can become blurry though, when are references to an other page important enough to be included in the article, and when should they be left out?

If we look at the example of the Bible, you could argue that references to other Bible verses should be included in the article, but you could also argue that this is extra information that doesn’t need to be carried over if someone were to transfer your content.

Section

Section is a rather misunderstood element. It often is not used by developers that use the other mentioned semantics. Section is a useful element that marks a section is a thematic grouping of content, typically with a heading. Examples of where a <section> element can be used:

  • Chapters
  • Introduction
  • News items
  • Contact information A web page could normally be split into sections for introduction, content, and contact information.

The <article> element specifies independent, self-contained content. The <section> element defines a section in a document. Can we use the definitions to decide how to nest those elements? No, we cannot! So, you will find HTML pages with <section> elements containing <article> elements, and <article> elements containing <section> elements.

This is generally speaking the top of your website, and in most cases is also a navigator for your website. A <header> element typically contains:

  • one or more heading elements (<h1> - <h6>)
  • logo or icon
  • authorship information Note that you can have multiple header elements, but that it cannot be placed inside of another header, a footer, or an address element.

A footer defines the footer of a document or section. A footer typically has (some of) the following elements:

  • authorship information
  • copyright information
  • contact information
  • sitemap
  • back to top links
  • related documents

You can place several footers in a html page.

The <nav> element defines a set of navigation links. Think of a table of contents, think of a header.

Important notice

Notice that NOT all links of a document should be inside a <nav> element. The <nav> element is intended only for major blocks of navigation links.

Browsers, such as screen readers for disabled users, can use this element to determine whether to omit the initial rendering of this content.

So then why use a <nav> if you already have a <header>, aren’t those the same? You are correct in seeing that sometimes they will overlap, but there are cases where you’d only want to use a Header, and there are also cases where you’d only want to use a Nav.

Aside

The <aside> element defines some content aside from the content it is placed in (like a sidebar). The <aside> content should be indirectly related to the surrounding content. This could be a table of contents or links to related articles etc.

Note again that whilst an Aside might have a lot of overlap in the use of a Nav, that they are not the same. Quick rule of thumb: If the content is for navigating, use <nav>.
If the content adds context, use <aside>.

Accessibility note

Assistive technologies treat <aside> as a complementary region landmark.
That means screen reader users can jump straight to the aside, but understand that it’s separate from the primary flow.
This is important for providing a structured and user-friendly experience.

Figure and Figcaption

The <figure> tag specifies self-contained content, like illustrations, diagrams, photos, code listings, etc. The <figcaption> tag defines a caption for a <figure> element. The <figcaption> element can be placed as the first or as the last child of a <figure> element. The <img> element defines the actual image/illustration.

<figure>
  <img src="pic_trulli.jpg" alt="Trulli" />
  <figcaption>Fig1. - Trulli, Puglia, Italy.</figcaption>
</figure>

Page Semantic rules

I assume that you already know this by the time you are reading this, but here is the gist of it.

HTML You only use this element once, at the top of your document. (but after the <!DOCTYPE html>) This tells browsers that it is a page they can format. It has a property called lang, and when you do <html lang="en"> crawlers will know what language it is.

HEAD The <head> is used for a lot of things, the rule of thumb is that it is for most things that will not be shown to the user visiting your page. The head is also the first thing that gets loaded when you visit a web-page, so it blocks the browser from rendering in the time it is loading the head. This is why it is encouraged to not put a lot of styling or scripts directly into the head.

  • The head tells the character encoding <meta charset="UTF-8">.
  • The head contains the <title>.
  • The head handles the viewport for responsive design: <meta name="viewport" content="width=device-width, initial-scale=1.0">.
  • The head can tell the page to download your (or someone else their) CSS files via <link>
  • The head has <meta> tags to tell apps how to show the website as an embedding.
  • The head can be used for <styles>
  • The head can tell the page to download a script.
  • The head can be used for structured data.
  • The head includes the favicon: <link rel="icon" href="/favicon.ico" type="image/x-icon">

BODY The body is the content of your website. You can view your HEAD to give browsers context about your page, and BODY to be the actual page. You put everything in your body which you do not put in the head.

Example of structure

To make the point clear of semantic elements, I’ll show you an example. This example will be based on the Bible since it is an easy to understand example.

First off you’ll have the 3 basic elements, the html, head and body:

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>
  <body>
  </body>
</html>

That is the easy part, but how would we design the rest? We want to make a page that shows the entire book of Genesis on a single page. (which you probably shouldn’t do because that is going to be a long web-page) The first thing that we’ll do is the page Header and a Nav in it, this is the header that redirects to our homepage and other possible pages we have, but not other bible books.

Then we’ll be arriving to the Main, our page is Genesis, so this will include everything about Genesis. In the main we can also add another Header with a Nav, this will have links to the other bible books. But we can also do this in an Aside instead of a Header, that is personal preference. Or do both if you want it to be responsive.

Then we get to the Article this will include the entire book of Genesis. This starts with a <h1> With the title of the Bible book. Then we will use a Section, this section includes the entire 1st chapter of Genesis. In this section we will put a <h2> with the title “Genesis Chapter 1” or something alike. Then after the header we’ll start to have to put text. So we will use a <p> element for the paragraph. And then inside of that <p> element we’ll put a <span> per bible verse.

This is the most logical way to use semantic elements with a Bible website. But then we get to the end of the chapters, this is when we want to put cross references and footnotes. You can either put this inside of the Article in a separate Section, or you can decide to put it outside of the Article. Like said in the Article paragraph, this is kind of a gray zone.

<!DOCTYPE html>
<html lang="en">
  <head>
  <!--Whatever you want-->
  </head>
  <body>
    <header>
	  <nav>
	    <ul>
          <li><a href="/">Bible.com</a></li>
          <!-- more links -->
        </ul>
	  </nav>
    </header>
    <main>
	  <aside>
		<nav>
		  <a href="#genesis">Genesis</a>
		  <a href="#genesis-1">Chapter 1</a>
		  <!--Some more links-->
		</nav>
	  </aside>
	  <article>
		<h1 id="genesis">Genesis</h1>
	    <section>
		  <h2 id="genesis-1">Chapter 1</h2>
		  <p>
		    <span data-verse="1:1">In the beginning God created the heaven and the earth.</span>
	        <span data-verse="1:2">And the earth was without form...</span>
	        <!--A lot more verses-->
		  </p>
	    </section>
	    <section>
	      <h2 id="genesis-2">Chapter 2</h2>
	      <p>
	        <span data-verse="2:1">Thus the heavens and the earth were finished...</span>
	        <!--A lot more verses-->
	      </p>
	    </section>
	    <footer>
	      <h2 id="article-references">References</h2>
	      <nav>
	        <!--depending on the content, might be better outside of the article-->
		    <!--Some links-->
		  </nav>
	    </footer>
	  </article>
	  <footer>
	    <h2 id="site-references">References</h2>
	    <nav>
	      <!--depending on the content, might be better in the article-->
		  <!--Some links-->
		</nav>
	  </footer>
    </main>
    <footer>
	  <p>&copy; 2026 Bible.com</p>
	</footer>
  </body>
</html>

Common mistakes

Below is a list of common mistakes that you should avoid when using semantic elements.

  • Using multiple <main> elements on a single page.
  • Nesting <header> or <footer> inside themselves, using a footer in a header or vice versa.
  • Wrapping everything in <section> without headings.
  • As mentioned in the article section, there are gray areas where you have to choose which makes the most sense to you, but when you make your choice, be consistent about your choice.
  • Skipping heading levels (e.g., jumping from <h1> to <h4>).

SEO Notes

SEO stands for Search Engine Optimization. There are some notes you should keep in mind about semantic elements if you want a good SEO score.

  • Screen readers rely on heading hierarchy (<h1>–<h6>). So use them logically. There should only be 1 <h1>, and there should not be gaps, like a <h3> directly after a <h1>.
  • <nav> and <main> give structure to assistive tech navigation.
  • Proper use of <article> and <section> improves content indexing.

List of elements

The main semantics

There are a lot of semantic elements, and some of them are common, some of them are not.
Here is a list of the common semantic elements:

  • <article>
  • <aside>
  • <details>
  • <figcaption>
  • <figure>
  • <footer>
  • <header>
  • <main>
  • <mark>
  • <nav>
  • <section>
  • <summary>
  • <time>

These are the elements people think of when you are talking about semantic elements.
But these are also semantic elements:

  • <html>
  • <head>
  • <body>

Other Semantics

Text-level semantics

These are semantics that give meaning to text — not just visual styling:

  • <address> – contact information for the author or owner.
  • <abbr> – abbreviation or acronym.
  • <cite> – title of a creative work.
  • <dfn> – a term being defined.
  • <em> – emphasized text.
  • <strong> – important text.
  • <small> – side comments or fine print.
  • <q> – short inline quotation.
  • <blockquote> – longer block-level quotation.
  • <code> – a piece of computer code.
  • <pre> – preformatted text (usually code).
  • <kbd> – user input.
  • <samp> – output from a program.
  • <var> – variable name or symbol.

These allow you to embed or describe multimedia content:

  • <audio> – sound content.
  • <video> – video content.
  • <source> – specifies media source files.
  • <track> – text tracks for <video> or <audio>, like captions or subtitles.
  • <picture> – container for multiple image sources.
  • <img> – still image with semantic alt text support.
  • <figcaption> and <figure> – as listed above, for annotated images or media.

Table semantics

These define the structure and meaning of tabular data:

  • <table> – table container.
  • <caption> – table title or description.
  • <thead> – header section of a table.
  • <tbody> – body section of a table.
  • <tfoot> – footer section of a table.
  • <tr> – table row.
  • <th> – table header cell.
  • <td> – table data cell.
  • <col> – column property definition.
  • <colgroup> – groups multiple <col> elements.

Form semantics

These define forms and user input fields with meaning:

  • <form> – form container.
  • <label> – caption for an input control.
  • <fieldset> – groups related form elements.
  • <legend> – title or caption for a fieldset.
  • <input> – input control.
  • <textarea> – multi-line text input.
  • <select> – dropdown list.
  • <option> – item inside a dropdown list.
  • <optgroup> – groups related options.
  • <button> – clickable button.
  • <datalist> – predefined options for input.
  • <output> – displays calculation or script results.
  • <meter> – scalar measurement (e.g., disk usage).
  • <progress> – completion progress bar.

References