Competent Classing

Published 14 years, 4 months ago

At last week’s Web Design Meetup, a couple of people showed me their current projects.  As is my wont, I glanced over the visual design and then started digging into the document markup.  In the course of the resulting conversation, I pointed out some ways to tighten up the markup.  I’ll repeat them here for those who are curious.  All of them relate to using classes and IDs efficiently.

The first recommendation I had was to use classes and IDs in conjunction.  Not everyone is aware that an element can carry both a class and an ID.  Well, they can.  So it’s no problem to have markup like this:

<div id="utilities" class="menu">

That way, you can style all menus consistently via the menu class, while having the utilities ID there for any ‘Utilities’-specific styling you need to do.  This has always been possible, and it’s supported by multiple browsers.  You don’t see it often, I admit, but then it’s not often needed.

The second recommendation was to use space-separated words in your class values.  This is thoroughly legitimate, and can make things a lot more compact.  So you might have something like:

<td class="subtotal negative">(-$422.72)</td>

You can then have one rule that styles all subtotals, and another than styles any negative number.  For example:

.subtotal {font-weight: bold;}
.negative {color: red;}

By using these kinds of class values, you can avoid having to construct one class for subtotal, and another for subtotal-negative.  If you’re doing that sort of thing, I can tell you right now that your CSS is larger and more complicated than it needs to be.  Multiple-word class names also free you from having to do things like throw in extra spans or other elements just to add more information, like so:

<td class="subtotal"><span class="negative">(-$422.72)</span></td>

That kind of structure is almost never needed, except in extremely rare cases where you must have an inline element on which you hang some presentational styles that can’t be applied to the table cell.  I can’t even think of a concrete example right now, but I’m sure there is one.  In which case, I’d say do this instead:

<td class="subtotal negative"><span>(-$422.72)</span></td>

But, as I say, the odds of your having to do that are very very low.

All this leads to a third recommendation that came to mind as I looked over the markup.  Remember to use document structure to your advantage, and not to class everything in sight.  I can’t tell you how many times I’ve seen this kind of markup:

<div class="navlinks">
<a href="blah01" class="navlink">Blah01</a> |
<a href="blah02" class="navlink">Blah02</a> |
<a href="blah03" class="navlink">Blah03</a> |
<a href="blah04" class="navlink">Blah04</a> |
<a href="blah05" class="navlink">Blah05</a>
</div>

Out of the six classes that appear in that markup fragment, five are completely useless and simply bloat the page weight.  Here’s a much more efficient way to structure the markup:

<div class="navlinks">
<a href="blah01">Blah01</a> |
<a href="blah02">Blah02</a> |
<a href="blah03">Blah03</a> |
<a href="blah04">Blah04</a> |
<a href="blah05">Blah05</a>
</div>

Now all you do to style the links is write a rule that uses the selector div.navlinks a instead of one that uses a.navlink.  In addition to making the HTML weight smaller, it also makes the document cleaner and a whole lot easier to read.  Your users don’t really care about that, of course, but I bet you will, if you ever have to go in and adjust either the markup or the content.

So there you go.  Hopefully it was of some help to you.

  • Published
  • Categorized under CSS
  • 45 responses so far

  1. […]

    Competent Classing  [Thoughts From Eric]
    CSS is even more flexible tha […]

  2. […] ec l’usage de Tiles. Toujours est-il que l’article d’Eric Meyer sur les meilleurs méthodes pour utiliser des classes en CSS tombe à poin […]

  3. […] ur redundant css code to allow for a much lighter more robust layout. Check it out here: Comments (0) –> Comments RSS feed fo […]

  4. […] use we have adopted an easier or sloppier way of doing it. WordPress blogger and CSS guru Eric Meyer has just stepped up with a timely reminder on the proper emplo […]

  5. Multiple classing is a good idea in theory, but I’ve found that it can be hard to keep track of which classes are contributing what styling in which context. This is something that one might be able to refactor in a second-round revision, although it’s still difficult to keep straight in your head, especially when you need to re-use one of those classes in a new context. Any tips on the mental juggling required?

  6. Adam,

    A tool such as the DOM Inspector that comes with the Mozilla family of browsers in an indepensible tool for sorting through things like cascading and figuring out which styles get applied in which order. Try it out sometime. There’s a ton more you can do with it.

  7. I’m using both of those techniques, because it makes life so much easier. By using “good” class names and ID’s, you can even make things almost self-documenting. (By “good” I mean names that specify what an element is, rather than what it looks like.)
    Mozilla’s DOM Inspector is extremely useful, although it crashes a bit too frequently for my taste. I find it invaluable when I’m looking for cascade- or specificity-related CSS problems, because it shows me exactly which CSS rules that are applied to an element.

  8. Don’t forget that you can use ID’s only once in the page. If you have a huge layout with different blocks it can happen to have collisions ;)
    What would be usefull is an elements map of the website, ordered by pages. (with XML it must be possible no ?)

  9. While I now remember that I’ve read about space-separated words in class values, I’d completely forgotten that you could sue them.

    Thanks to this reminder, I’ve just been able to remove a whole host of span tags from a table of data that I’ve been working on at work. (Sorry can’t post it here it’s “for internal eyes only”).

    Thank you yet again Mr Meyer for the always useful information!

  10. *use (please excuse my typo)

  11. Good stuff. I’ve been using selectors rather than classing a whole stack of link elements individually, but the idea of multiple class names is news to me, and a very welcome idea.

  12. Some great advice there. It’s always good to learn how to streamline CSS code and get rid of any divititus. Thanks for sharing your thoughts, it really put things into perspective.

  13. I think this is the next step in getting people to really understand how to optimize their CSS.

    Is there a limit to the number of classes you can use, I have only ever used 3 on one element, but wondering if it is limitless?

  14. I would assume the number of classes is unlimited, in theory. I’ve never heard anything about a limit.

  15. Very helpful. Thank you as ever, Eric, for your time devoting to teaching.

  16. good common sense advice, nicely worded as always.

  17. Excellent write up.

    A good rule of thumb to help remember how and why to avoid classes that are:

    useless and simply bloating the page weight

    is Context before class.

    Another good rule of thumb (which I need to add to a pending update to “A Touch of Class“) is “Class for meaning, not for show“. I’ve seen far too many class attributes recently like class='black', class='grey', class='clear', etc. (from folks who should know better), with respective rules like .black { color:#000; } , .grey { color: #999; }, .clear { clear:both; }, etc. Such presentational class names are not much (if at all) better than presentational attributes like color='black', color='grey', clear='all' etc. It may require a bit more analysis, but it is always better to think of class names that represent the meaning/function of the specific element(s) rather than what happens to be their current presentation. That way when their presentation changes (as it inevitably does), or alternative presentations are designed for additional media types or devices, you avoid such confusing style rules like .black { color:navy; } etc.

  18. Might I also point out that using multiple classes is of tremendous value if you use the brilliant float-clearing routine at positioniseverything.net to clear your floats. Whenever I have a container div I need cleared, I just give it a class of “twocolumn clearthis” or “threecolumn clearthis” etc etc etc. That way it picks up the style rules from the first word and the clearing behavior from the second word.

  19. Good article, though for completenes you might want to include Tantek’s point about naming classes (and ids) for their function rather than appearance.

    I do think one area might be explained with more clarity, though. You talk about “multiple-word class names”, when you actually mean “multiple-word class attributes“. A class name can’t include spaces, a class attribute can contain multiple space-seperated values. Of course you know that, but it might not be clear to the novice given the way it’s worded.

  20. Ok, you lost me. I will have to read this again. This is [very] interesting. Keep up the good work! ;)

  21. Oh, Eric. I just got through two intensive weeks of rebuilding the structure of the blog, and along come these nuggets! The idea of unlimited classes attached to one element is very intreaguing. Still, I finally got rid of the class=”menulist” attached to every sidebar link, by doing something similar to one of the points above. Getting leaner and cleaner…

    You sure you ain’t got time to do another book for that publisher you were talking about? How many more of these gems are you storing up?

  22. Good article. We also have been trying to minimize our CSS by reusing classes like content. We place it in a div at the beginning of a section, and define how it should behave if it encounters href’s, li’s or p’s rather than making separate link, list or pargraph classes.

    .content {color:#000}
    .content a {color:#06c}
    .content a:hover {color:#bbb}
    .content li {color:#090}
    .content p {color:#b00}

  23. Unless i’ve made an error somewhere, there seems to be a bug in ie when using id and class together. The code below should render a blue background in ie but renders it in red instead.
    CSS:
    #outer {background:red;}
    #outer.test {background:green}
    #outer.inner {background:blue}
    HTML:

    This is red in Ie and blue in moz

    If you change class=”inner” to class=”test” then the background is green as expected. This makes it impossible to set up different classes for different templates for example. I know there are other ways of doing this but thought it might be interesting to know.

  24. Of course, you also pointed out the fact that the last example there should be an unordered list, right? ;)

  25. I’ve been taking this approach now for a while – both using multiple class names and fully utilizing the “cascade” by wrapping blocks of content in container DIV’s. I find it to be a very efficient way of working, it really speeds up the process, and to me at least, makes my CSS far more readable.

    However, it seems to run against the grain of the whole semantic markup brigade, whose unnatural bias against non-semantic markup tags like DIVs and SPANs puzzles me. Take the following two examples:

    <– Begin Semantic Block –>
    <h1 class=”header”>Header Text</h1>
    <p class=”paragraph”>
    Paragraph text
    </p>
    <ul class=”list”>
    <li><a href=”#”>link</a></li>
    <li><a href=”#”>link</a></li>
    </ul>
    <– End Semantic Block –>

    <– Begin Efficient Block –>
    <div class=”myclass”>
    <h1>Header Text</h1>
    <p>
    Paragraph text
    </p>
    <ul>
    <li><a href=”#”>link</a></li>
    <li><a href=”#”>link</a></li>
    </ul>
    </div>
    <– End Efficient Block –>

    Of course, this is really simplified – assume that both examples would be in the context of a complicated document which would prevent you from directly styling the HTML tags directly. The first example is more semantically “pure”, but involves class bloat – the only case in which you can take advantage of descendants is the unordered list. By wrapping the entire block in a semantically meaningless div, you gain a lot more power to manipulate the contents without adding classes to every element.

    To me, this is the real power of non-semantic tags. Many web authors who’ve picked up a bit of semantic zealotry tend to avoid using non-semantic markup at all, which is kind of silly – in much the same way that attempting to build a tabular grid without using a table is. Of course, we should remember to mark up semantically meaningful content using semantically meaningful tags, but there is nothing wrong with using non-semantic tags to “wrap” your meaningful structure.

    I’d even go so far as to say there’s nothing inherently wrong with wrapping a block of meaningful content in four nested layers of DIVs to achieve a specific visual effect – the non-semantic markup just provides you with the “hooks” you need to get the job done, and should properly be ignored by any media that doesn’t use it.

    The only disadvantage I can think of is that perhaps search-engines would rank a H1 wrapped inside a DIV lower than a root-level H1, but I’m really not even sure if this is true.

  26. I’d like to further clarify the point explained in Comment #18. It is actually a “space separated list of classnames”. Even though the term “multiple-word class attributes” is correct it is not clear for the novice what we are talking about, while when we say “multiple classnames” there’s no question about it.

    Also, the example in Comment #23 works with DIV fine. IE notices onlythe first complex selector, in this case #outer.test. If you swap them it will ignore #outer.test and consider #outer.inner. Too bad!

  27. Dear Eric,

    Can an active anchor be used in a media=print stylesheet?

    In screen mode my links will display the choice image flawlessly but will fail miserably when I want to print. Does the status or focus of the link temporarily change when printing?

    Thank you in advance for your reply.

    Nell

  28. […] ugh an ID and class. It is also possible to style with multiple cases. More info here: http://www.meyerweb.com/eric/thoughts/2004/07/18/competent-classing/ >> Debu […]

  29. Hi Eric! Why do you use it like this?

    Blah01 |
    Blah02 |
    Blah03 |
    Blah04 |
    Blah05

    Do you use CSS?

  30. I’m sorry, Milos, but I don’t understand your question.

  31. […] Competent Classing, by Eric Meyer […]

  32. […] Competent Classing, by Eric Meyer […]

  33. Hi Eric,

    verry good CSS coding. Thanks for the tipp.
    Greeting from Germany
    Sven Fischer

  34. Hey now Eric!

    Your example of the presentation of a negative number subtotal,
    (-$422.72)
    seems to overlook the fact that the use of red (via CSS) obviates the need for parentheses and minus sign.
    That is, parentheses are an old-fashioned accountant’s method for indicating a negative quantity (when numbers must be black), while the minus sign is the traditional mathematician’s method for doing the same.

    To repeat the point another way, parens OR the minus sign OR red type all indicate individually that a number is negative. It’s odd to use more than one of these methods simultaneously.

  35. The example <td class=”subtotal”><span class=”negative”> is perhaps best substituted by <td class=”vcard”><span class=”fn”> – as used in microformats, which require classes on nested elements.

  36. You say, That way, you can style all menus consistently via the menu class, while having the menu ID there for any “Utilities”-specific styling you need to do. I think you mean the utilities ID.

  37. Exactly so, Evan! I’ve updated the post to fix that very embarrassing error. Thanks for bringing it to my attention.

    Funny that nobody else noticed or mentioned that in the 3.5 years since I wrote the post. Well, that’s why I leave comments open indefinitely!

  38. I believe Milos is asking why you use the vertical bar character in your list of links. In fact, when I’d seen that, I wanted to ask the same question.

    I would have done something like this:

    <ul class="navLinks">
    <li><a href="blah01">Blah01</a></li>
    <li><a href="blah02">Blah02</a></li>
    <li><a href="blah03">Blah03</a></li>
    <li><a href="blah04">Blah04</a></li>
    <li class="last"><a href="blah05">Blah05</a></li>
    </ul>

    I’d then apply a border-right to all li tags except the last (accessible by the ‘last’ class)

  39. Ah! Thank you, David, for clearing that up.

    Of course, it’s been almost four years now since the original post, so I don’t recall the original project constraints—there may have been some reason that a list wasn’t acceptable in those circumstances. Doing things the list way is certainly a fine way to go; I’ve done it myself many a time. Doing the links as bar-separated text also works, of course, though it doesn’t offer nearly the same level of styling flexibility.

  40. Does multiple class pose any performance issue Vs a single class used to define a Block,

    Vs

    where in four are in single CSS File, so the server request is 1 only.

    .w120{width:120px;}
    .h120{height:120px;}
    .fleft{float:left;}

    .blockA={width:120px;height:120px;float:left;}

  41. for the above post
    /div class”w120 h120 fleft”> Vs <div class”blockA”/

  42. […] Competent Classing, by Eric Meyer […]

  43. Hum, sorry to have to break the mighty 42 number of comments, but I think you should really get rid of the weird phrasings:

    “space-separated words in your class values” : gramatically correct but VERY misleading
    “Multiple-word class names” : utterly wrong ! These are multiple class names.

    It really looks like you did not understand the mechanism altogether.

    An element can be assigned multiple classes. Period. No fuzzy magic involved.

    Make no mistake, I find your taking time to share your discoveries very valuable, I am doing by best to do it myself. Keep going.

  44. But don’t you pay a performance penalty with div.navlinks a as opposed to div.navlinks a.navlink?

    With the first selector, anytime the browser comes across an anchor element it has to march up the DOM to see if it is a descendant of a div.navlinks. A document may very likely contain dozens or even hundreds of anchor elements that are not a descendant of a div.navlinks. Each of these anchors incurs a performance penalty even though the selector does not match.

    With the second selector, anytime the browser comes across an anchor element it simply needs to check if it has the class navlink. If it doesn’t, then it can dismiss the CSS selector for this anchor.

    See http://code.google.com/speed/page-speed/docs/rendering.html for details on using efficient CSS selectors.

  45. […] am again standing on the shoulders of giant’s regarding the markup, and in particular and keen to adopt Malarky’s conventions […]

Leave a Comment

Management reserves the right to edit or remove any comment, especially when abusive or irrelevant to the topic at hand. HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <em> <i> <q cite=""> <s> <strong> <pre class=""> <kbd>


Comment Preview

If you're satisfied with what you've written, then go ahead...