“Classy” HTML

Or how to make <div> soup


tl;dr version

  1. Enough with the <div><div><div>… already!
  2. HTML & CSS offer a wide variety of attributes – classes are just one of them, and sticking to classes religiously is only restricting yourself
  3. Classes can be effective. Sometimes better options exist.
  4. Classes should be thought of as categories
Most developers or designers will fall into one of two extremes when it comes to assigning classes in their HTML – everything needs at least one class or classes are only for special circumstances. Who is right?

The truth is, neither are. Well, you might also say that both are. This isn't a one-size-fits-all sort of issue. It depends on your markup, where and how it will be used, what role it plays with the rest of the site, who will be authoring content (if it applies), and personal preference.

In my opinion at least, the abuse of classes is a direct result of a lack of semantics in HTML. It's better now with the introduction of new tags in HTML5, but for a long time <div> soup was (and kinda still is) the norm.

Screenshot of the HTML at wordpres.org
This sort of markup is no longer necessary thanks to new tags in HTML5. To give the typical example…
Where we might have done this
<body>
<div class="header">
<h1>…</h1>
<div class="nav">

</div>
</div>
<div class="sidebar">

</div>
<div class="main">
<div class="article">
<div class="header">
<h2>…</h2>
</div>
<div class="section">

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

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

</div>
</body>
we can now do this
<body>
<header>
<h1>…</h1>
<nav>

</nav>
</header>
<aside>

</aside>
<main>
<article>
<header>
<h2>…</h2>
</header>
<section>

</section>
<footer>

</footer>
</article>
</main>
<footer>

</footer>
</body>
Although only slightly smaller, it looks much cleaner and is easier to read. In the former <div> soup example, it makes a lot of sense to be riddled with classes. Of course, as the HTML becomes more complicated you lose the simplicity and clarity of a <div>-less DOM tree. But, even still, the necessity of tags is reduced due to a wider variety of available tags that are descriptive of their role in the document.

That makes sense for smaller stuff, but what about…?

You've got me there. Everything I've ever written myself (admittedly faily simple stuff) hasn't required that complicated of markup. Come to think of it, if your markup is that complicated, I'd tell you to question if it's really necessary. Taking Facebook for example, I would imagine it could be done as follows:

<body>
<header><!--That damn blue bar at top-->
<input type="search">
<nav>…</nav>
</header>
<aside><!--Left sidebar-->
<menu type="list">
<li><a><img>…</a></li>

</menu>
</aside>
<form><!--Create Post-->
<button type="button"><img></button>
<button type="button"><img></button>
<textarea></textarea>
<button type="submit"></button>
</form>
<main><!--Center Column-->
<section><!--An individual post, containing imgs-->
<header>
<a><img></a>
</header>
<figure>
<img>
<figcaption>…</figcaption>
</figure>
<footer>
<!--comments-->
</footer>
</section>
<main>
<aside><!--Right sidebar-->
<ul><!--Ads-->
<li><a><b></b></a></li>

</ul>
</aside>
<footer><!--Actually on the right side-->
<a></a>…©
</footer>
</body>

What do they actually use? 4789 elements with class, 2747 <div>s, and 1224 <span>s. No <header>, no <footer>, no <aside>. What's even more surprising is that I see <body> has a class of Locale_en_US… More about that soon.

Sidenote, <div>s & <span>s are generic and meaningless tags. They should be used only as a last resort when no better tag fits. There are plenty of other options to choose from.

I know that it's a lot more complicated than that, and I am in no way saying that it doesn't make total and complete sense for there to be a few classes thrown in there for various reasons, but this markup should cover the skeleton of it, and I havene't even gotten into data-* or other attributes yet.

You criticized Facebook for having a Locale_en_US class?

Yep, I did just that.Why? Because there's an attribute for that. It's called the lang attribute and can be read about here.

Why would I complain about that?

  1. They already use the lang attribute on <html>
  2. lang actually has meaning, whereas the class doesn't
  3. Like most attributes, lang has both name and value, making it more useful, and can be accessed though
    1. JavaScript: document.documentElement.lang
    2. CSS: [lang=en]
  4. Even if they didn't want to use the lang attribute, they could have used something like data-locale="en_US", which has many of the same benefits

Classes are not always the best way to set something apart. They are mostly of value when it comes to CSS and JavaScript, and usually have no real meaning to anything else. I like to think of them as categories or qualifiers for tags, and only use them when something is not distinct enough in its relation to the rest of the document (DOM tree) or if I want to do the same thing to something that is unrelated and there is no better method.

When it comes to useful selectors other than class, data-* really stands out for being useful because it can be used pretty much however you like.

  • As a general selector: [data-samp]
  • As a name-value pair: [data-samp="value"]
  • As a selector & in a rule:
    [data-samp]::after {
    content: attr(data-samp);
    }
  • Advanced selectors: 
    • Beginning with: [data-samp^="v"]
    • Containing: [data-samp*="alu"]
    • Ending with: [data-samp$="e"]

As a practical example, something that I use a lot, and something that would not be nearly as easy if I were to limit myself to using classes only.

[data-icon]::after {
font-family: 'Web Symbols';
content: ' ' attr(data-icon) ' ';
}

Sure, I could make classes for every possible character using class="icon_{$char}" and then go though in CSS and apply essentially the same style with different content to each, but why make it some much more difficult?

All of these are true for any non-boolean attribute (such as hidden or disabled). You can use role, type, rel, href, etc.

As a very practical example of where using attributes is superior to classes, consider the common practice of using .button. It is far better to use role="button" & [role=button] because that actually has semantic value to it.

Things become even more interesting and powerful in JavaScript, which I have surprisingly not talked about very much in this.

Imagine all of the cases where this would be useful:

var results = document.querySelectorAll('[data-x]');
for(var n = 0; n < results.length; n++) {
results[n].addEventListener('click', function() {
myFunction(this.dataset.x);
});
}

or if you prefer something more like jQuery (I actually don't know jQuery or if it has a data() method)

$('[data-x]').click(function(){
myFunction(this.data('x'));
});

This is exactly why the JavaScript for my WYSIWYG editor is only 16 lines long! I seriously wonder why this practice isn't more common considering that these selectors go back as far as IE7.

So, I should just not use classes at all?

I wouldn't go that far, but if you have no reason to use them and don't feel so inclined, you could easily not use them without consequence.

I would say that classes are useful for grouping together things which have nothing else in common or for setting apart things which should be distinct from similar items. For example

.fullwidth {
display: block;
width: 100%;
}

There's just no better way of achieving that. You wouldn't want to use a tag here because you probably don't want it applied to every one of them. You also might want to apply this style to any wide variety of elements that are totally unrelated (an <img> here, a <div> there). You could use data-width="full" or something similar, but that just makes it a bit more complicated and has no benefit.

Classes are especially useful when creating widgets. Odds are, you'll be making something to display poll results or weather info (so a <div> would actually be the correct tag to use) and it is likely to be moved from place to place, so you cannot style based on its parents. In such cases, classes are extremely useful. In fact, when dealing with <div>s and <span>s, I would say that you should probably always use at least one class because they are so meaningless and indescriptive.

One last thing to consider. If you are a developer or designer and someone else provides the content (as might be the case in a blog), keep in mind that writers won't want to have to memorize a bunch of class names to use in order to get a particular style. Do you think anyone would use Microsoft Word if it required you to manually add attributes to achieve different effects? Instead, try providing a wider variety of tags. Let your writers focus on content instead of code.