Luciano Battagliero

§Semantics in HTML and CSS

Published on

Few topics in front-end development have been debated as long as semantics. The conversation has been going on for well over a decade, and it tends to go in circles.

Part of the reason it keeps coming back is that most of the debate comes from applying semantic rigor where it has no technical basis.

§HTML Element Semantics

HTML elements have agreed-upon meaning. A button is interactive. A nav represents navigation. A ul is a list. Browsers, screen readers, and search engines understand these elements and act on them. The meaning is formalized and machine-readable.

Using the right element when one exists matters. It provides accessible defaults, keyboard behavior, and structural information. But a div is not unsemantic. It’s semantically neutral. It communicates nothing, which is different from communicating the wrong thing.

Adding elements to support styling or layout doesn’t remove meaning from anything around them. A wrapper div doesn’t make its children less semantic. It just exists alongside them, saying nothing, affecting nothing structurally. Using elements beyond the bare minimum needed to markup the content doesn’t make the HTML unsemantic.

The idea that every element must justify its existence semantically sounds reasonable in theory. In practice, markup serves multiple concerns: content structure, accessibility, styling, and layout. Sometimes an extra element is just the right tool to make a component more robust or flexible. That’s fine.

Use the most appropriate element when one exists. But accept that sometimes the ideal element isn’t practical; layout constraints, styling requirements, or third-party code can get in the way. When that happens, a div or span with the right ARIA attributes can communicate the same intent. Semantics aren’t all-or-nothing; a less specific element doesn’t remove meaning from the document, it just provides less of it.

§Class Name Semantics

This is where most of the confusion lives. The idea that class names should describe the content, not the presentation, has been treated as a fundamental rule for years. The HTML5 specification even encourages(opens in new tab) it:

[...] authors are encouraged to use [class names] that describe the nature of the content, rather than [class names] that describe the desired presentation of the content.

But this recommendation is ideological, not technical. Nothing in the platform enforces or benefits from it.

Class names carry no meaning for machines. Browsers don’t parse them. Screen readers don’t interpret them. Search engines don’t use them. A class is a hook; a way for developers to connect HTML to CSS and JavaScript. That’s it.

Content-layer semantics are already handled by HTML elements, attributes, and standards like ARIA and Microdata. Duplicating that information in class names doesn’t add any value.

This doesn’t mean class names are meaningless. They communicate something, but to developers, not to machines. And what’s most useful to communicate is often not what the content is, but what the component does.

Consider a class named .news. It tells you nothing about the component’s structure, and it can’t be reused for anything that isn’t news. A class named .card tells you what the pattern is. It’s more reusable and, arguably, more informative.


In practice, the industry moved on. Component-based architectures co-locate markup and styles at the component level, making class name conventions less relevant, and utility-first CSS is extremely popular because developers chose pragmatism over ideology.

None of this is new, but the argument keeps coming back. This post is my way of not having to say this twice.


§Reading List

Filed under #technical

Subscribe to the RSS feed