What Makes For a Semantic Class Name?

Chris Coyier //

Semantics in HTML is always a hot topic. Some people strive for it at all times. Some people critisize a dogmatic adherence to it. Some people don't know what the heck it is.

I'd describe semantics as it relates to HTML as tags, classes, IDs, and attributes describing but not specifying the content they enclose. Let's start with an example we can probably all agree on.

Bad Semantics

<div class="article">
  <div class="article_title">Smurf Movie Kinda Sucks</div>
  <div class="the_content">Not surprisingly, this weeks release of
     <div class="darkbold">The Smurfs</div> kinda sucks.</div>
</div>

Good Semantics

<article>
  <h1>Smurf Movie Kinda Sucks</h1>
  <p>Not surprisingly, this weeks release of
     <b>The Smurfs</b> kinda sucks.</p>
</article>

Whether or not you think HTML5 is ready to use or not, I think you would agree that when you need an HTML element for an article, that the <article> tag is better than a generic <div> with a class name. The title of the article becomes a header, the content becomes a paragraph, the bold-but-not-emphasized title becomes a bold tag.

But not everything maps that cleanly to HTML tags. Let's look at a bunch of class names and I'll offer my opinion on if I think it's semantic or not.

<div class="column_1"></div>

Unsemantic. This is a classic example. Every single CSS grid framework in the world uses some kind of class names to declare the grids. Whether it's "yui-b", "grid-4", or "spanHalf", all of these are closer to specifying than describing their contents. So while I maintain these are unsemantic class names, I also think they are largely unavoidable in float-based grid-system layouts.

<div class="footer"></div>

Semantic. While a footer is an abstract concept, it has come to have meaning in web design. It's the bottom of a website the typically contains things like repeated navigation, copyright, author info, etc. This class name declares a group for all that stuff without describing it.

If you've made the leap to HTML5, the <footer> element would be better. And that goes for all the HTML5 elements. (Headers should be <header>, sidebars should be <aside>, etc.) If you aren't yet using HTML5 (you better have a really compelling reason), the equivalent class names I feel are fine.

<div class="largeText"></div>

Unsemantic. This is specifying. Why should the text be larger? To stand out from other smaller text? "standOut" or "callout_text" might be better here, as in the Theoretical Redesign Future™, you may wish to choose a different style to make that text stand out that has nothing to do with the size of the text, and you won't be stuck with an awkward class name.

<div class="priority-2"></div>

Semantic. I've talked with some folks from MailChimp (Jason Beaird and Aarron Walter) about this and this is how they declare the relative importance levels of buttons within the app (Although with class names more like "p1" .. "p5"). Higher priority buttons might have brighter colors or be larger, while lower priority buttons might blend in more with the content. By not being specific with what those styles are and abstracting to a priority level, you are staying semantic. It's like taking the idea of <h1>, <h2>, <h3>, etc. to buttons.

<div class="copyright"></div>

Semantic. If only every class name was this easy! This goes for any section which contains content that is easy to describe with a word like "tweets", "pagination", or "admin-bar". Although with that last one, you'd be better off calling it "admin-nav" as in the Theoretical Redesign Future™ this area might not be a "bar" anymore.

<p class="introp"></p>

Unsemantic. I saw a presentation with Dave Rupert one time where he joked around that this was his favorite class name. I can totally relate to that as it's such a common scenario to style the first paragraph of a page differently, like an attention-grabbing overview to get people into an article.

If you absolutely need super deep browser support, you might need some kind of class name, in which I'd say "intro" is better than "introp" (leave the element name out of it). But much better would just be to target the first paragraph like article p:first-of-type or h1 + p.

<div class="clearfix"></div>

Unsemantic. This is an extremely common class name, which applies a bit of trickery to get the element to contain all of its decendant floats rather than collapse. But it has nothing to do with the content it contains, thus unavoidably unsemantic. Dan Cederholm recommends a more feel-goody class name "group" for this purpose instead (in his book Handcrafted CSS), which, to me, just barely brings this into the realm of semantic, as certainly this wrapper contains multiple other elements and is thus a group (describing without specifying).

<div class="left"></div>

Unsemantic. Perhaps in the Theoretical Redesign Future™ you'll want this stuff on the right instead. Too specific.

<div class="success"></div>

Semantic. I think this one works best in conjunction with other class names so that one of them describes the content and one describes the status of that content. Like "success message" which could hold a message like "Your file has been uploaded!". If that message was "There was a problem uploading your file." the class names could be "fail message" instead and have appropriate styling.

<div class="plain-jane"></div>

Unsemantic. This is trying to specify that the content inside should be styled a specific way. "plain-jane" is the same as something like "normal" or "regular". Ideally CSS should be written so that you don't need class names for "regular" styles, that just comes by default through the cascade, and anything that breaks that in unusual ways gets a class.

<div class="entry-unrelated"></div>

Unsemantic. Readability, the web app for reformatting and saving web pages for ease-of-reading later, has you use this class name to specify parts any elements of your site you don't want to be accidentally included in the conversation/saving of your article. The reason I'm going unsemnatic here is because it's describing what it's not, not what it is. I wish there was something other than a class name that could be used for this purpose. Sort of like rel=nofollow for links, but for content.

<div class="hyphenate"></div>

Unsemantic. Trying to specify the behavior of the content inside, instead of describe what it actually is.

<a class="link" href="#"></a>

Unsemantic. While link is descriptive without being specific, just the nature of an anchor link already makes it a link, thus not necessary. If the class name is trying to separate this link from other "normal" links, be more descriptive as to why, e.g. "book-link" or (debatable) "button".

But...

Let's say you have two types of articles on your site and you want to style them differently. Movie Reviews will have a blue background and Breaking News will have a red background and bigger text.

Here's one way to do that:

<article class="movie-review">
   ...
</article>

<article class="breaking-news">
   ...
</article>

and another:

<article class="blueBg">
   ...
</article>

<article class="redBg bigText">
   ...
</article>

I bet if we had a poll and asked people which example they thought was more semantic, the first would win. It fits the bill put forth in this article: describing without specifying. Whereas the second example specifies ("blueBg" is a class name that applies a blue background). Let's say the Theoretical Redesign Future™ stops being theoretical and is now in progress. The design for movie reviews now has a green background. The class name "blueBg" is rather awkward there. Whereas the class name "movie-review" is totally fine and you just change the properties/values to do the green background instead.

This isn't to say the first example is hands-down always better. Let's say that light blue color is used in a lot of places on the site. Perhaps it's the background color of a particular part of the footer and a particular sidebar box as well. You might end up with selectors like:

.movie-review, 
footer > div:nth-of-type(2),
aside > div:nth-of-type(4) {
   background: #c2fbff;
}

That's efficient because you are only declaring that color once. But it's also a rather complex, hard-to-scan, unwieldily selector. Not to mention those different selectors may need unique styling, so they'll have to be repeated later. Or you take another approach and just leave them separate:

.movie-review {
   background: #c2fbff;
   /* Plus other stuff */
}

footer > div:nth-of-type(2) {
   background: #c2fbff;
   /* Plus other stuff */
}

aside > div:nth-of-type(4) {
   background: #c2fbff;
   /* Plus other stuff */
}

That might actually keep your CSS file more organized (keeping different areas of the site in different sections) but at the cost of repetitive declarations. In a presentation by Nicole Sullivan I recently saw at the CSS Summit, she called out some big companies for declaring the exact same color in the CSS files literally thousands of times. I think we can all agree that's crazytown. There may be a variety of solutions to that, but one of them might be using a class name like "blueBg" to declare it once in the CSS and then put the burden on the HTML for applying that class name when you want that design. Still, you'd be better off calling it "mainBrandColor" or "secondaryFont" as to avoid specifying. As I understand it, that's OOCSS. Sacrificing a slight bit of semantics for the greater good (drastically smaller resources).

Would love to hear some of your opinions on all this. I'm sure plenty of you have other example, different opinions on what is or isn't semantic, and whether or not that matters.