Ode to Semantic HTML

Eevis - Nov 28 '20 - - Dev Community

Have you ever created a button out of a div? Added that onClick-event there, and styled the div to look like a button? Yup, me too. And I'm not proud of it.

If you wonder why I'm saying I'm not proud of it, here's the reason: It is purely exclusive. If you don't add the correct roles, the tab index, keyboard events, and all that, there are plenty of users who just can't use that button. Heck, some users don't even know that there is a button.

In this blog post, I will explain what semantic HTML is and what are the benefits of using it. A spoiler alert: They help to communicate that there actually is a button. 😄

What is Semantic HTML?

Semantic HTML, or semantic markup, describes its meaning to browser and developer in human- and machine-readable way. So, with semantic elements, a human will know what that element is (for example, a button), and a browser knows how to display and interact with them. An example:

<button onClick={handleClick}>I am a button!</button>
Enter fullscreen mode Exit fullscreen mode

vs.

<div id="button" onClick={handleClick}>
  I try to be a button!
</div>
Enter fullscreen mode Exit fullscreen mode

As a reader of the code, you probably can assume that the first one is a button from the button-element. That is a semantic tag. <div> however, is not a semantic element, and without that id on the div, you wouldn't be able to say that it is a button (well, it says "I try to be a button!" but the text could be anything).

From the browser's (or eventually, screen reader's) perspective, that first one is definitely a button, as the semantic tag tells. The latter, however, is just text, so no possibilities of interaction - screen reader users don't know that there is a button at all. Sighted keyboard users see that it is a button (assuming it has been styled as one) but can't interact with it as it does not get focus.

A note here - not all native elements are semantic elements. Elements like <div> and <span> don't carry any semantic meaning, and thus are not semantic elements. The elements and features I'm discussing in the next section, are only the ones with semantic meaning. For all the curious ones, every HTML element is explained in the WHATWG HTML Living Standard. I like the note about the div-element:

Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable. Use of more appropriate elements instead of the div element leads to better accessibility for readers and easier maintainability for authors.

Semantics can be communicated through two things - native semantics and semantics added with ARIA (Accessible Rich Internet Applications).

Native Semantics

Native semantics come from the HTML elements. The HTML element itself conveys meaning - eg. that it is a button - and does not need any extra (like role="button") to be added to the mix. This is maybe even clearer with the code-element. When the browser encounters a code-block that has been declared with the code-tag, it knows that there is no need to try to run that code. It is purely for reading and happens to be code.

Semantic HTML-elements also carry lots of other good things - they are focusable and keyboard usable by default to the extent that particular element should be. There is no need to implement these features. So, in the example of the button, it can be activated with enter and spaceBar, and our code doesn't need to listen to the spacebar or enter key events.

Other examples of (natively) semantic HTML elements are headings, paragraphs, and landmarks such as header, main, and footer. They can be grouped into several categories such as document metadata, text-level semantics, grouping content, etc. See the WHATWG HTML Living Standard for more information.

One note about using semantic elements: use them for their semantics, not for their looks. A good example of misuse is using blockquote-element for the indentation AMD not for implicating a quote.

Semantics with ARIA

There is another way to add semantics to the elements, and that is with ARIA. For example, a span with the following properties is not understood as a heading by a screen reader:

<span>I want to be a heading!</span>
Enter fullscreen mode Exit fullscreen mode

But when the semantics are added with ARIA, it becomes a heading from the screen reader's point of view:

<span role="heading" aria-level="2">Yay I'm a heading!</span>
Enter fullscreen mode Exit fullscreen mode

Note, however, that the semantic heading tags are the recommended way to communicate headings! And this goes to anything - native semantic HTML elements are preferred over adding semantics with ARIA. The reason for this is that when using ARIA, there are so many things to remember to implement and add compared to the native semantic elements.

So, when the ARIA would be an appropriate solution compared to semantic HTML? There are several occasions, and a common nominator is that when the semantic elements aren't enough, ARIA should be used. For example, there is no semantic element for a tabbed interface. To make it accessible, it would need a few aria-attributes and roles added. If you are curious about what those things are, check out the WAI-ARIA Authoring Practices - they have listed design patterns for different widgets containing the expected keyboard interaction and needed aria-attributes, and have the information for tabs as well.

There is a warning to be given when speaking about ARIA. No ARIA is better than bad ARIA - this means that having the wrong aria-attributes in the code can create a really confusing experience for users with assistive technology. Also, when using, for example, roles, be sure to implement all the functionality that is expected from that role - it is frustrating if a screen reader tells that the element is a button, but the keyboard functionality is not implemented.

So, I want to stress this: adding ARIA adds just information, not the functionality. When using aria-attributes, be sure to implement all the expected functionality!

Why You Should Use Semantic HTML

The HTML tags we use should describe and convey the meaning of the underlying content. This is helpful in many ways, but the three most important things are 1) making the site accessible, 2) helping with SEO, and 3) making the code easier to read and understand.

Accessibility

The first point, making the site accessible, should be every front end developer's goal. I mean, I imagine no one wants to exclude any users, right? Making the site fully accessible to different kinds of users requires a lot of work. Using (native) semantic elements helps you, as you don't have to implement every single interaction by yourself, as the semantic tags provide most of the required functionality.

SEO

Semantics also helps with SEO. Search engines crawl through the websites and can only "see" the textual context and DOM, and they index the content they come across. This means that everything that is in textual format counts. For example, giving images descriptive alt-texts, using semantic headings, and so on, help make your DOM machine-readable for crawlers, yielding a better SEO score.

Readable Code

Using semantic elements also helps to make the code more readable. An example:


<div>
  <div>
    <div onClick={...}>
      Home
    </div>
    <div onClick={...}>
      About
    </div>
    <div onClick={...}>
      Contacts
    </div>
  </div>
  <div>
    <span>Blog</span>
  </div>
</div>
<div>
  <span>Title of the blogpost</span>
  <div>
    Cat ipsum dolor sit amet, chase 
    ball of string or try to hold own 
    back foot to clean it
  <div>
</div>

Enter fullscreen mode Exit fullscreen mode

vs.

<header>
  <nav>
    <ul>
      <li>
        <a href="/home">Home</a>
      </li>
      <li>
        <a href="/about">About</a>
      </li>
      <li>
        <a href="/contacts">Contacts</a>
      </li>
    </ul>
  </nav>
  <h1>Blog</h1>
</header>
<main>
  <article>
    <h2>Title of the blogpost</h2>
    <p>
      Cat ipsum dolor sit amet, chase 
      ball of string or try to hold own 
      back foot to clean it
    <p>
  </article>
</main>
Enter fullscreen mode Exit fullscreen mode

Which one is easier to read and understand what's going on? I'd say the second.

Summing-up

So, using semantic HTML is the thing to do for several reasons; It helps to build accessible sites, to get better SEO-scores, and make the code more readable. You can add semantics by using the native elements or with ARIA. If you use ARIA, be sure to use the correct aria-attributes and implement the functionality that is required (so, for example, don't communicate that "this is a button" with role="button" but then neglect to create the keyboard shortcuts).

I'm planning to write several blog posts that dive deeper into the design patterns and widgets in WAI-ARIA Authoring Practices and implementing them with React. So stay tuned if you want to know more!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .