CSS Strategy Square-off
Doug Avery, Former Senior Developer
Article Category:
Posted on
It’s an exciting time for CSS. On top of the advances being made both in what to write (CSS3) and what to write with (SASS+Compass, Less), CSS is enjoying a spate of serious discussion over how it should be written.
This might come as a suprise to some (and did to me). After all, CSS seems pretty straightforward — without many of the complexities of programming, CSS has long been seen as something you just write. After all, it’s not particularly hard to write good CSS and markup; so long as your definition of “good” means “looks right, seems consistent, has semantic value”, you’ve generally gotten a pass.
The question recently posed is: is this definition of good, originating from the dark ages of table layouts, good enough to deal with the problems CSS encounters in 2011?
The answer might depend on a few things: first, whether you observe such problems, and second, whether you see them as sufficiently difficult to work with. As I see them:
What Goes Wrong With CSS
- CSS grows with site size. Depending on your site, this can be a serious issue — not just for performance, but because CSS is code. More code tends to lead to more problems — maintaining code size is a serious concern.
- CSS best practices encourage what would otherwise be bad programming: repetition, bad grouping, loose coupling. Again, if you treat CSS as code that needs to be maintained, reviewed, and refactored, these are negatives.
- CSS is often contextually unreadable. For example,
.about .main ul li li a
might be very clever CSS, using a nesting in the markup to trigger a style, but it’s very bad code — without a strong understanding of the HTML, this code can be ambiguous, and its HTML target hard to pinpoint. - CSS encourages overrides, which are the death toll for maintainability. The more styles you override, the more styles you will eventually have to override again.
- CSS encourages bad coupling and distant dependencies — for example, let’s say all LIs inherit a margin-bottom we set early in the CSS, and the features we code design with this spacing in mind. Despite the fact that the art director says a particular feature MUST look the way the comp looks, said feature now depends on a very remote line of code, a line that anyone might change without realizing the consequences.
If your response to #4 was “well, don’t let them change it”, it's a valid one and probably puts you into the “current CSS thought is alright as-is” camp. And that‘s okay! IMHO, your mileage with these complaints is a factor of your experience with large sites and with others’ CSS, but most importantly, with your tolerance for workflow friction.
Personally, my friction tolerance is pretty low — untangling overrides, for example, is something I tend to avoid at all cost, even when that cost involves burning more time finding a stricter naming solution. So, the approaches of SMACSS and OOCSS have a certain appeal to me. They both propose to add a little work (and sometimes a lot of classes) onto the front of the buildout process, but supposedly pay off with cleaner, shorter, more explicit CSS.
Big props to Sullivan and Snook for tackling this issue and facing a new age of CSS challenges with their work. You should definitely consider both proposals for yourself (SMACSS, OOCSS), but to sum up my thoughts on the value of each (alongside the traditional CSS/markup methods), here’s a big ol’ comparison table.
CSS Systems, Compared
Classical | SMACSS | OOCSS | |
---|---|---|---|
Markup: | Superclean. Classes are only added when completely necessary for styling. | Many elements with classes. (Elements inside distinct modules, however, can remain classless.) | Start classing, and don't stop until you run out of classes. Some elements will have 4, 5, 8 classes. |
Markup semantics: | Straightforward. Write the markup you want, style it the way you want. In my experience, classical HTML/CSS will encourage you to reuse particular elements to achieve particular styles — for example, setting an H3 as a page header because of inconsistencies found in a later comp. | Flexible. By relying on classes, not elements, SMACCS allows you to use the appropriate markup for the job without worrying about existng styles. | Very flexible. You won't be styling any elements in OOCSS, and you might find that it allows you to pick much more appropriate tags in some cases. |
Class semantics: | Great. Classic CSS books have example like “.entry”, and its friends “.entry p”, “.entry .byline”, etc. The markup reads well, and the classes are highly descriptive of their content. | Starts to wobble. Now that you're classing for two — meaning and style — you’ll be forced to make a few concessions. There will be some new classes that don't really reflect content, but provide valuable hooks for your CSS. | Pretty rough. In OOCSS projects I commonly find myself writing <li class='highlighted-news-listitem news-listitem listitem'>, when in a perfect world, I would just write “<ul class='news'><li class='highlighted'>... |
HTML size: | Teeny. The teeniest! | Classing more explicitly will increase your pagesize. | Classing VERY explicitly, and using multiple classes to apply styles, can add a good chunk to your HTML. A recent project of mine had a 20% increase in HTML filesize. |
CSS size: | Big and getting bigger. Once you pass a certain project size threshhold, CSS begins to increase 1-to-1 with new layouts. | Small. | Also small. Writing explicit selectors allows you to whip out new designs in no time using a rich palette of existing classes. It’s actually really surprising the first time it works, and really cool. |
Stuff that makes a programmer grimace: | Gross overrides, low readability, bad coupling, repetition, writing more code to fix problems that result from too much code. | Not too much. Some less-than-readable classnames. | All those damned classes! Having 5+ classes on an element is a guarantee that a few will get botched in integration. |
Stuff that makes an FED grimace: | Overrides. Using longer selectors to cancel out previous styles is, and has always been, unpleasant business. | Child selectors = IE6 problems. I know that I just need to get over IE6, but it burned me so bad — I’m nervous about adopting a system that fails so hard in IE6. | <h1 class="h2"> Nicole's abandonment of fully descriptive classnames is backed by good reasons, but it's a hard pill to swallow. I end up compromising with classes like "subtle-header" and "pronounced-tight-header", which are slighly less vague but also, somehow, more ridiculous. |
Misc. performance: | Longer selectors are generally slower in CSS, but not to a degree that users would notice. | Has lots of classes and the occasional ID, which make for great JavaScript hooks. | Selecting by class is pretty efficient. No IDs can mean no good, fast place to start a DOM query. (Of course, you can just add IDs for JS purposes if needed) |
This is just a list of quick impressions, but I wanted to get it out there and get some thoughts from other CSS devs. In my reviews, OOCSS provides a more explicit pattern, while the SMACSS proposal has a deeper, yet more interpretive style. OOCSS is suited for seriously huge sites, while SMACSS provides a middle ground suitable for mid-sized projects. Both are excellent and worth your time to read.
Does CSS need fixing? Do SMACSS or OOCSS do it for you? Do you have more ideas for the table, or do you think I mis-represented anything? Are you Jonathan Snook or Nicole Sullivan, and if so, will you sign my yearbook? Let me know in the comments!