Semantic CSS

Subtitle: Why everybody who talks about the importance of semantics is both right and wrong at the same time.

I’ve often heard people talk about semantic CSS. That is, the names we come up for IDs and class names should be meaningful.

When people say “semantic”, I think they do so in a way that assumes that we all know what it means. Yet, the way it’s normally applied is never quite clear. Maybe we could look to something and nod approvingly when told that the “.products” class name is, of course, semantic.

So, what do people mean when they say that we should use semantic class names. It usually means that the names we choose should describe the content contained within.

For example, if you have a list of products, the class name would be products. If you have a list of events, the class named would be events. And so on.

There’s little consideration within this naming convention to how things look. It’s about describing what they are.

Why do we want to use class names that describe the content?

In the case of Microformats, meaningful class names provide a hook for other sites, applications, and add-ons to use the embedded data. There are about a dozen different specifications that you can use in your projects.

For the purpose of styling, however, browsers don’t care whether the class names are meaningful or gibberish. It’s only useful to us humans and its usefulness is quite minimal. What do you care whether it’s a list of products or not? How does knowing that it’s a list of products help you in styling said list of products?

One thing that I’ve seen from people who use this type of semantic classes aren’t necessarily consistent in how they apply this throughout their project.

Along with products, events, and collections, they’ll have class names like navigation, dropdown, and modal which don’t actually describe the content. They describe the design function.

The Design Function

Describing the design function—what the thing actually does—is important. We use patterns within our design to establish a learnable and consistent interface for users to learn. These design patterns are codified in our CSS. Therefore, the class names we choose help inform us when we’re building an interface.

Names that describe a design function allows us to ensure that we’re using and reusing interface elements in the right way.

Defining products, events, and collections separately allows differences between those interfaces to crop up. (Although, yes, people use a preprocessor’s ability to “extend” to help mitigate these issues.) Having multiple classes when a single one will do also increases CSS bloat.

They say there are two hard things in programming: off-by-one errors and naming things.

For example, on the workshop page, I had a number of locations that I highlighted with a blue background and rounded corners. I called it location since it highlighted each of the locations I was doing a workshop.

When I opened the online store, I had a list of products and wanted to highlight each product using the same design pattern. Problem was, they weren’t locations. They were products. Being the lazy developer I was, though, I just reused the location class and applied it to my products. Clearly not ideal (but hey, it worked)!

The design function was, of course, to highlight something. That was what I should’ve called it!

When a project starts, it might seem like we’ll only use a style in one place. As a project evolves, those one-offs will often creep into other elements throughout the site. Choosing something that defines the design function instead of the content contained within allows reuse of that CSS much more readily.

After all my years of developing web sites, I still instinctively fall into using content-based class names instead of function-based class names. I have to be diligent and thoughtful in my development.

Generic Functions

Now, trying to come up with class names to describe its design function can sometimes be easy, like button, navigation, or dropdown. Sometimes, with more generic chunks, it can be quite difficult.

Take a look at this example from the Twitter web site.

Twitter cards with call to action
Twitter cards with call to action

What do you call this? Are they cards? That would probably be confusing since Twitter calls their embedded tweets cards. This is where it gets difficult.

I remember at Yahoo!, we had a similar dilemma as we were building out a new feature. What do you call a generic container with varying content? We pulled out the thesaurus and end up settling on the word pod. I still felt a bit awkward about the name we settled on.

This is where documentation can be important, too. If you have a card, box, and pod in your project, when do you decide when to use which?

Gray Area

Some names could be considered content-based but could still also be considered function-based.

Let’s look at the Engadget web site.

Engadget cards with call to action
Engadget cards with call to action

Engadget called each of these a lede. This might feel like it’s describing the content but I’d say it satisfies the functional test. The purpose of this design piece is to present a lede to entice the visitor to read the article. An article and lede are generic enough to be applied to pretty much any kind of content, whether it’s a tech story, a news story, an editorial, or whatever.

It’s that genericness that is the important part.

What if Engadget wants to present ledes in different visual styles? This gets a little bit tricky. Why? Because I like components to be distinct visual styles. If different ledes are presented in distinct visual styles, I’d avoid them using the same root module name.

For example, in SMACSS, a module name would be lede. If we named this alternate but distinct lede style as lede--special then you end up having to know that this special style is meant to be standalone and not layered onto the standard lede. It also means that other variations and child elements are likely not applicable with this variant.

In which case, come up with a unique module name. It might be special-lede or uber-lede or intro or whatever your team decides to come up with.

A rose by any other name…

I feel like every post I write these days should come with a disclaimer. This is not dogma. This is a process that has worked well for me. With a bit of forethought, thinking more about the naming convention has reduced the need to refactor code as often.

Using my location class to highlight a product didn’t hurt anybody. No babies died. Buildings didn’t crumble. It won’t be the end of the world. But sometimes a bit of clarity can go a long way to making the maintenance of a project more enjoyable.

Published May 26, 2016
Categorized as HTML and CSS
Short URL:

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.