Pedantic about semantics

The role of semantics within design systems.

Dan Webb
Dan Webb
Industry, Engineering, Design Systems

In this article

In HTML there are three list elements that are considered semantic:

  • Unordered list (<ul>)
  • Ordered list (<ol>)
  • Description list (<dl>)

Browsers apply a default user agent style to modify the appearance of these elements. This is where a problem presents itself – we have a list of items but the default browser list styles are not wanted.

Using plain <div> tags would get us the right style, but shouldn’t a semantic list element be used instead?

To be able to use the sematic list element a new component or class would be need to be created to conditionally undo the browser styles. That’s a bit of a pain.

To add to the effort, in this case the need for an unstyled list is turning out to be a common global pattern, so the new styles would need to be part of the central design system.

Is it really worth all the effort of a new design system release? There’s not even any visible list styles! Aren't we just being pedantic about semantics?

A list should be a list

Writing semantic HTML involves structuring the web page using elements that convey meaning.

The meaning is separate from the appearance, content or functionality of the element, but it does inform both human and machine of what the element is for.

We could write the list as:

<div>Content</div>
<div>More content</div>
<div>Even more content</div>

That would get us roughly the appearance of what we want - an unstyled single column of elements sat on top of eachother.

The <div>s share no semantic meaning at all so the only thing that could make this a list is a human interpretation of either the content placed inside them or their appearance on the webpage.

Here’s the same thing using semantic list markup:

<ul>
<li>Content</li>
<li>More content</li>
<li>Even more content</li>
</ul>

Regardless of the content or appearance meaning can be gathered from this.

  • <ul> - it’s an unordered list, we want the contents to be grouped as one list but it doesn’t matter what order the items display in.
  • <li> - a list item, the contents of this element represents one item within a list of items.

You might think calling it a ul and li is stupid, but it doesn’t really matter because semantics is more than opinions or naming, it’s about there being a non-subjective shared meaning.

In HTML the meaning is openly documented through a specification that browsers aim to consistently adhere to across every HTML page. So we don’t have to invent or document ways to structure all these elements between projects, it’s already sorted.

The hidden benefits of semantics

Okay, we’ve called a list a list, but only developers and machines will see this, nobody else will care, it still feels like we’re being a bit pedantic.

As we’ve already spoken about semantics isn't about the final output, but the shared meaning does inform both human and machine what the output should be (a list).

For example, screen readers and other assistive technologies read the semantic meaning of elements out loud to describe the content to users.

Here's a video showing the two implementations of the list from earlier being read out by Mac Voiceover.

As expected, the semantic <ul> element gets read out as a list:

  • “List with 3 items”
  • “Content 1 of 3”
  • “More content 2 of 3”
  • “Even more content”

The contents of the <div>s on the other hand are read out with no grouping or indication of what the items are meant to be part of.

Assistive technologies are just one example that leans on the consistent application of semantic HTML elements – any tech that crawls web pages like search engines rely on semantics to accurately read the content, browser user agent styles rely on them to apply default styles that make the webpage readable and functional in the absence of CSS or JS.

We can’t be sure how all these technologies will make use of the semantic elements in the future. What we can be sure about is that if we don’t use the semantic elements then no intended meaning will be shared to benefit end users.

Applying semantics within a design system

Hopefully by now we’re convinced that semantics are important, so let’s go right back to how to approach the original problem – it should be clear that we should not just form this list using plain <div> elements.

Something not mentioned yet that might be tempting here is the availability of ARIA role attribute which would at least get us similar accessibility benefits to the semantic list.

<div role="list">
<div role="listitem">Item 1</div>
<div role="listitem">Item 2</div>
<div role="listitem">Item 3</div>
</div>

This would be against the first rule of ARIA and for good reason – remember there’s three different semantic list elements in HTML? This role only covers one with no user agent styles.

In the MDN documentation for this role it states:

Only use role="list" and role="listitem" if you have to — for example if you don’t have control over your HTML but are able to improve accessibility dynamically after the fact with JavaScript.

The point is this: as design system authors, we should do everything in our power to avoid restricting consumers on their use of semantic HTML elements.

Getting into implementations, that might look like this with “HTML web components” which wraps around the semantic markup:

<ds-list list-style="none">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</ds-list>

Or in Angular which supports component attribute selectors:

<ul ds-list list-style="none">
<li ds-list-item>Item 1</li>
<li ds-list-item>Item 2</li>
<li ds-list-item>Item 3</li>
</ul>

Or using as props in JSX based frameworks like React, in this case it’s important to also spread the props onto the underlying element to make sure all the HTML attributes are supported:

<List as="ul" listStyle="none">
<List.Item as="li">Item 1</List.Item>
<List.Item as="li">Item 2</List.Item>
<List.Item as="li">Item 3</List.Item>
</List>

No matter the implementation, it should be our responsibility not to hide away or restrict use of semantic HTML elements and provide guidance within the design system documentation to advise on how to use them.

Moving beyond utilities

As we’ve seen HTML gives us so much hidden power for free by relying on the shared meaning of semantics causing a consistent application of the right elements in the right places. Semantics are important!

We could stop where we our with the now semantic list component, most generic lists could use it and it’d be a good improvement.

But a design system should create and document a shared meaning around specific entities within the problem space. We can take HTMLs lead when considering custom design system components – if all we had in the design system were utility components it would be a bit like using <div> elements everywhere in HTML.

For example, if we take this imaginary list scenario and consider it from a semantic point of view, we might notice our product(s) include this list when the content is a reciept like price breakdown in carts and payment checkout flows.

In this case a more semantic implementation could look like:

<price-breakdown>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</price-breakdown>

Suddenly, this begins to form more meaning, it’s not just a list, it’s a price breakdown list and in turn that informs the output “this is how price breakdowns look and behave in our product”.

In the same way as semantic HTML, the price breakdown components output is detached from the meaning which leads us to hidden benefits such as the ability for the appearance or functionality of price breakdowns to be targeted and then used, adapted or improved globally over time without having to edit every instance.

This shows the power of using semantics to inform our decisions around building and using design system components. All through considering semantics we’ve gone from a meaningless unstyled set of elements and ended up with a future-proof and accessible semantic design system component.

Etch is a web software consultancy based in the UK©2012-2024 Etch Software Ltd - Policies