Playing Nice with the Other CSS Kids

by Mike Stenhouse

published 29 October 2005

Simon Willison recently posted to css-d asking for peoples' thoughts on writing maintanable CSS and that got me thinking... Over the years I've had the privilege of working on some very large web standards projects in small teams of other CSS/XHTML developers, but I've also spent a lot of time building little sites on my own for smaller clients. Maintenance on a small project involves being able to understand your own code when you come back to it months later. On larger projects it means your team mates being able to understand and edit your code as quickly and efficiently as possible at any point in the future. It's a far more complicated objective.

My CSS Framework and Modular CSS articles touched on maintainability but here I am going to expand on those ideas, and attempt to suggest some guidelines to make team CSS coding and maintenance easier.

Bite sized pieces

If you have read my previous articles you will already know that I favour breaking my CSS down into manageable pieces. I started doing this back in early 2003 when I coded the first few versions of business.gov.uk with 3 other developers at Nykris (now defunct). In the first phase of the project I developed a base set of templates and extracted from them the core stylesheets and and an HTML framework. In subsequent phases, each member of the team then took these as their starting point, adding their own section- or page-specific CSS files. This isolated the individual pages and sections but ensured a consistent overall look. The complicated version merging that a single large file would have required was also avoided. The small section/page sheets had a defined purpose and could easily be digested by any other member of the team, requiring less orientation.

The major drawback to this approach comes when the client decides to make changes that effects the base files. These changes cascade through the entire site, which is great, but with so many small files following up on the new developments can get time consuming. The answer is obvious - get a detailed project specification finalised and signed off at the very beginning... But it's never that simple. Web projects are organic and like it or not the goalposts move. I don't really have an answer to this problem - I believe that there has to be some trade off between the team environment and flexibility.

Self-documenting code

The base HTML featured meaningful ids and classes, as good web standards practice suggests. This is a concept that bears a distinct similarity to ideas I've come across recently as part of the Extreme Programming methodology: the class and method names should make sense when read as a sentence, resulting in self-documenting code. The rationale is that programmers hate documentation. How many people ever read it? How many people know how to write it well? The number of times I've come to comments in code that bear no relevance to the code itself because a developer (often me!) has forgotten to update these embedded tips in his rush to get the job done... Using sensible, meaningful ids and classes is as close as we can get in HTML and CSS to this self-documentation nirvana.

Take this CSS snippet:

div#content div#main p.intro

Anyone can look at that, figure out what is going on and find the effected HTML in the source without any trouble. I am restyling the introductory paragraph in my main content div. Simple. In the source that is a <p class="intro"> inside <div id="main"> inside <div id="content">.

Sandboxing

The little snippet above also demonstrates something else... I tend to over-specify my rules. Classes and ids aren't orphaned (div#content instead of #content) and as much of the path is specified as possible (div#content div#main p.intro instead of just p.intro). Yes, this increases the size of the resulting stylesheet but when anyone else comes to look at it they will be able to see generate their own HTML from the CSS, if necessary. It makes for heavier code but far better maintainability...

Over-specifying also helps to avoid name clashes later on. I've heard this approach called 'sandboxing', which describes it very well. Sandboxing your CSS to apply to a very select set of elements and widening it only when required helps you keep a tight reign on your code as it expands.

If you take a look at my CSS Framework HTML you will see that every page section is given an ID. Within those sections I tend to use classes (I'm not going to get into when to use classes vs ids here). This clearly separates the rules for each part of the page.

Controlled use of !important

If you want sandboxing to work for you properly you should make sure that you keep away from !important as much as possible. I use it almost exclusively as a debugging tool - if something isn't behaving as I expect it to, I will add !important to the rules... If !important cures the problem then my rule is under specified, otherwise it's something more complicated.

Controlled use of !important is essential when your CSS is distributed across several files. I ran into this problem on the business.gov.uk project while trying to set the width of an input button - for some reason it just wasn't working. After trawling my way up through the cascade I eventually found that someone had added width: 30px !important to the core forms.css file. Poor practice and wasted time.

Redundant rules

In addition to overspecifying I also tend to reuse sets of rules. I set margins and padding as a pair even if I don't strictly need them. My most common layout problems come from unintentional inheritance so I use this redundancy to attempt to minimise the chance of this happening.

Consistent naming conventions

Over the years I have come up with a consistent vocabular for ids and class names that I reuse across projects. Most of these ids are documented in my CSS Framework article but there are a few classes that turn up again and again too - things like 'promo' for promotional spots and 'intro' for the unique styling often applied to introductory paragraphs. This is hardly rocket science but I find it helps when it comes to maintenance. Once a member of the team becomes familiar with the naming conventions they can edit the CSS without constantly having to refer to the HTML source code.

Version control

Back on the business.gov.uk project we used the most lo-fi of all versioning systems: Comments at the top of the code, emailed files to a single developer in charge of the CSS source (that thankless task fell to me as lead developer) and shouts of "You got x open?". This didn't really work, creating no end of accidental overwrites, but the deadlines were so tight that we couldn't afford the time to stop and implement a proper versioning system. I would never work like that again.

Since then I have become a convert to CVS. CVS is a brilliant piece of technology allowing automated versioning, diffing and merging of text files, with a more basic set of tools for binaries. This means that several people can edit the same file all their changes can be merged together automatically.

CVS's successor, SVN, provides very similar functionality but with a few enhancements. On css-d Alan Stevens explained the importance of SVN to his team's workflow:

We do lots and lots of projects for smaller customers, and it became impossible to try to remember the details of them all. Also, customers would ask for changes, and then after everything was live would ask for roll-backs of some of the changes ("we want this, no we dont, we want this, no we dont..."). We solved the problem with Subversion (http://subversion.tigris.org/), an open-source version control system. We now have a history of everything that was done for a client, and it's easy to roll things back. At first it seemed like overkill, but now I can't imagine working without it.

I've been working with CVS on a large project for about 6 months now and I can't imagine getting by without it either.

Intelligent commenting for easy scanning

Last but not least is formatting the stylesheets for easy consumption later. A consistent format for your team's source code will allow anyone to make changes with the minimum of orientation. This is good old common sense and anyone who's ever worked on ANY programming project in a team environment will understand the benefits.

I surround all id blocks with:

/* THE ID IN CAPS */ 
    .... 
/* END THE ID IN CAPS */

And all class blocks with:

/* the class in lowercase */ 
    .... 
/* end the class in lowercase */

I also indent child blocks by one extra tabs each time to give me a visual representation of the cascade and specificity.

The resulting code looks like:

/* MAIN */
    div#main {
    }
    /* intro */
        div#main p.intro {
        }
        div#main p.intro strong {
        }
    /* end intro */
/* END MAIN */

Doug Bowman has suggested using what he calls 'flags' in your comments to aid the finding of blocks of code in large stylesheets, which are also worth considering when you come to work on your next project.

The road to maintainable team CSS

This set of guidelines is by no means the last word in the art of writing maintainable CSS but I hope it can mark the start of a broader discussion. They have worked for me on both large and small projects but I would love to hear how other people tackle the same problems.

Comment

  1. Great article, and very timely for me as I have just started working on a large project which involves handing over HTML and CSS to the client’s developers.

    I’m a little wary of sandboxing as I’ve seen it go wrong and make it very difficult to apply sitewide changes. That may have just been poor execution of the concept though ;-).
    Roger Johansson    31 October, 4:56pm    #
  2. I’ve had trouble with it as well but I’ve got myself into a proper pickle doing it the other way too so I’ve gone for the ‘least damaging’ route! The drawback of sandboxing is that it gives you more refactoring to do as the project goes on; the benefit is that you retain a tight grip on your code, which is very useful for debugging…
    Mike Stenhouse    31 October, 5:27pm    #
  3. Excellent article! I too have some issues with sand-boxing but more and more I am inclined to reduce the size of individual sheet and have them target specific areas. This also allows for modular coding as I use a lot of “includes” of modular components.

    As to in-document information and sheet presentation I am in the process of redoing a huge number of sheets to improve this aspect and allow for others to maintain.
    Rob Cochrane    31 October, 6:45pm    #
  4. If you like subversion you’ll love this:

    http://www.bigbold.com/snippets/posts/show/42

    It ssh-s into your server, checks out the latest copy and symlinks it to “latest’. And if you need to roll back you can just change the link.
    Ben Jackson    31 October, 8:35pm    #
  5. Interesting article. I definitly agree with the points you’ve raised, however, i do believe that keeping the css together in one file means you can be much more consise in your css.

    Also, i think !important shouldnt be used like you’ve mentioned, even for debugging. Like you mentioned, begin really specific from the start, stops this problem from occuring in the firstplace.

    To get around your redundancy problems, I think simply resetting global atrributes saves everyone problems, and also allows you to use semantic XHTML better too ( for accessibility ).

    You didnt mention anything about hacks, I hope your like us, in that creating proper XHTML and specifying css properly you can get around without using them :-)

    CVS ftw.

    Cheers
    Simon    1 November, 1:47am    #
  6. Do you think there is any issue when using sandboxing in the resulting file size increase? It seems in real world use, it doesn’t make that much of a difference, but some CSS references stress using shorthand as much as humanly possible, splitting the CSS into multiple files, each under 4k for cache reasons, etc.

    I personally try to write self-documenting code as well, although I’m the first to admit in favor of speed it’s not always written for others to comprehend as easily as I can. I also break out my CSS as much as possible (declaring margins and paddings explicitly everwhere especially) but don’t follow the practice of sandboxing where everything is written out as div#content div#index p.intro like your example. I think that might be ultimately easier to understand but not as efficient – with the web developer extension for firefox and a search in the CSS file, it seems pretty easy to figure out the containing element and its code in the CSS.
    Jacob    1 November, 5:02am    #
  7. Great article. Nice reading for the beginning of my day :-)

    Ciao Marco
    Marco    1 November, 8:17am    #
  8. Simon: what’s the problem with using !important for debugging (during the development process, as I take it mike means)?

    Also for the hacks, I don’t think you raise a fair point here. I definetly favour a very clean XHTML with a hacked css (I use * html, html>body and the /*\*/ hack for mac IE) to a solution where you create more divs to get margin/padding consistent or insert clearing elements to get around the float problem.
    Anyone with me here? Mike?
    Pascal Opitz    1 November, 8:33am    #
  9. Re: Hacks:
    I think this can be a very emotional discussion. Essentially there’s 3 things:
    – using hacks
    – using extra markup
    – adding extra markup via DOM

    When you’re in the situation that you’re not designing the site, and your designer doesn’t know much about code or standards, you’ll quickly end up having to use at least one of these possibilities. I used to happily hack my way through css, but at some point I decided to ditch that approach in favour of extra markup (where possible).
    Recent hints of MS to use conditional comments instead of *html seem to support that.

    [edited] Now, lately the semantic markup-lovers seem to be in fashion. (Changed this, as it seemed inappropriate) [/edited]
    Use the markup as a semantic structure and add everything else via DOM, and I’m not sure what to think of this. It reduces the total number of people getting a visually “correct” page, by taking out the no-javascript people. It possibly favours alternative views on the site (screenreaders? but they do the script as well, at least a little, right?), but, statistically speaking, who’s the winner, besides the coder’s eye?
    Matthias Willerich    1 November, 11:34am    #
  10. Simon:
    !important can save hours while debugging and I can not see any reason for not using it for that purpose… Care to expand on why you think it should be avoided ALL the time?

    The global whitespace reset wouldn’t help with the redundancy problem – that’s caused by inheritance through the cascade, not default settings. I tend to avoid the whitespace reset anyway because when handing templates over to clients you can guaruntee that they will use an element that you didn’t think of in a content area that never occurred to you. With all whitespace reset you will get them on the phone complaining every time; with defaults in place things might just look okay.

    Simon & Pascal:
    The only hacks I use are * html and /* \*/. As a result of my accessibility background I am a semantic purist and those two hacks allow me to avoid the wrapper divs and other extraneous markup that some people use to get around box model problems. Basically, what Pascal said!
    Mike Stenhouse    1 November, 11:42am    #
  11. Jacob:
    I totally agree that sandboxing can lead to less efficient code. I use it as a trade off with maintainability… I have found that overspecified rules are a lot easier to (re)familiarise myself with at a later date, making maintenance a less painful process. It’s up to you how much extra code you need versus how quickly you want to get bug fixing months or years down the line.
    Mike Stenhouse    1 November, 12:51pm    #
  12. Good and valid points!

    @Matthias: WTH [edited /]
    Jens Meiert    1 November, 3:18pm    #
  13. [edited/]: I think matthias is making fun of people that consider a standard-compliant but in 75% of the cases non-usable so-called solution a better way than coding a site with a couple of hacks that works in non-standard-compliant browsers.
    Pascal    1 November, 3:32pm    #
  14. Well, yes and no,

    There are designs, that don’t allow for lean code on its own. In the end I work in a job where I can’t choose the design (or, for a fact, the interface altogether) that I’ll build. If I’m lucky, I’m not up to my neck in work while the design-phase for the next project happens, so I can comment on it.

    The luckier ones either design and build the site, or have designers that are aware of web standard-friendly design; and sadly that can come with a bit of a non-understanding attitude.
    Matthias Willerich    1 November, 6:14pm    #
  15. I cant say i’ve ever used !important for debugging, and have never really needed it as such, so thats why i dont really think its nessecary as a debugging tool. I prefer to use firefox’s web developer extension – it provides much more useful information much faster too.

    Pascal, hacks are nasty, thats why i beleive there called hacks. If you resolve the problem that nessecitates a hack ( generally IE6 box model problems or mac IE float / clear issues ) and follow w3c standards, you actually don’t run into issues, and don’t need them. I’ve made several sites which run on the most popular browsers ( IE6, 5.5, 5, firefox, mac IE, safari, opera etc) without using one hack. The sites even work on cellphone browsers, screen readers and the like. Its all about careful use of css, and the application of semantic XHTML. using it the way it was intended. :-)

    The best way to acheive this I believe is to first develop your layout css, and browser test at this stage. Globally resetting margins, padding, font-size, and list style will let you develop your layout css, without the need for hacks. Also the knowledge about why the problems occur, and avoiding them can also help.

    Most of the time were in the same boat as Matthias, we only get to choose the technical side, markup and server code for a particular design, so choosing the correct way to do it is definitly important.
    Simon    1 November, 10:10pm    #
  16. Btw, Box model problems can always be solved by not applying padding to an element you specify a width too.

    In most cases, you can actually avoid this problem by being careful with your css :-)
    Simon    1 November, 10:17pm    #
  17. Simon: I don’t wanna start lecturing, but to be honest I don’t think you are right here. What if you want to have a box on the site with padding AND a width?
    Either you nest two elements, one with a set width and one with padding inside, or you HACK the css to make it work. In that case I’d rather save one element and hack the css. Wich by no means affects the validation though.
    The same thing goes for boxes that have floated elements in them. I’d rather use the “holly hack” than find myself using something like a clearing div.

    Another recommandation that you gave, resetting margins, padding, font-size and so on can lead to serious trouble as well.
    If you ever used relative font-sizes (em or %) you’ll find that you’ll have to be damn carefull about where you specify the font size, since they will be inherited, and 75% of 75% is not what you thought it should’ve been anymore.
    Also when you work with content-driven CMS engines you’ll get to the point where the client inserts markup in places where you didn’t expect them, like a list or a p and so on. A general reset of margin and padding will let those appear in a way that will be percieved as broken, unless you overwrite the reset for every element that could contain user defined markup.
    Pascal Opitz    1 November, 10:54pm    #
  18. Picking up on the point about “Team Maintainable CSS” ~ I have found that breaking your design into layers (Structure, Typography and Colors/Theme) can bring some big benefits for large team based projects.

    This is mostly true where both designers and developers are involved. You can for instance give a designer the “theme” template to work with, thus shielding them from complex structural CSS. On the flip side, developers can forget about the pretty colors, concentrating on just the structure of the interface.

    It is a technique that’s paying dividends where I work.

    I’ve explained in more detail in a recent article.
    Andy Peatling    1 November, 11:13pm    #
  19. It is in fact a similar sort of idea as “Manageable Pieces” link you provided in the article. ;)
    Andy Peatling    1 November, 11:16pm    #
  20. Cheers Pascal,

    I understand where your coming from. I guess we need to make the desicion to either use slightly duplicate markup ( to control the box model problems), or use hacks in css.

    There are many browser bugs that can be solved by other, non hack means, eg. adding a line-height to a parent element to solve IE 6’s Peak-a-boo bug instead of the holly hack etc. – Thats more what i was meaning with the other IE hacks and things not related to box model problems.

    :-)
    Simon    2 November, 2:08am    #
  21. Good tips help to write CSS clean and manageable for future. :)
    Joerg Petermann    2 November, 4:38pm    #
  22. Simon and Pascal:

    Looks like you’ve reached an amicable agreement on hacks, which is nice! Thought I’d wade in with one more point. The cleaner your HTML the easier your code is to understand. I’ll explain…

    On the HTML side you have less chance of missing a closing div if you only have a handful of them. I only mention this because the development version of my new site has wrapper divs everywhere and I keep breaking it by forgetting to close them. In the final version they will be added with a little DOM script.

    In the CSS, wrapper divs tend to come with generic names like ‘wrapper’ ,’content’ , ‘extra’, etc. I’ve had trouble in the past with nesting these. For example, if your ‘page’ div needs one and your ‘content’ div also need one then you can get unexpected cascade/inheritance issues.

    I much prefer clean HTML and minimal hacking on the CSS. I find it much easier to keep all my compromises are in one place – the CSS, instead of being split between HTML and CSS.

    That said though, I’ve also had my share of trouble with the * html hack, in particular, when I’ve changed the width on the original rule and forgotten to reflect the change in the hack and then spent ages trying to track down what had gone wrong… Yet again, it’s a trade-off.
    Mike Stenhouse    3 November, 11:59am    #
  23. I’m sure glad this list of maintainable css doesnt say to never use shorthand – as did someone else’s guide written a couple months ago. LOL
    — David    3 November, 10:10pm    #
  24. Great article mate.

    Ive delivered templates to 3rd parties and used to endure banging-head-against-the-wall emails to developers trying to change the font-color in a div.

    Ive been using ‘sandboxes’ in my css for a while now and I can estimate about a 95% reduction in headaches. Its proven kids.
    sermad    7 November, 3:54pm    #
  25. Hey guys thanks for your comments :-)

    I might try your ‘framework’ Mike on our next project, and we’ll see what happens :-)

    Cheers!
    Simon    8 November, 9:00pm    #
  26. wonderful article
    — James    16 March, 11:09pm    #

Have your say

If your comment doesn't show up straight away, please don't be offended - we're not censoring, we are just trying to keep out all the viagra and poker ads. Thanks to an explosion of spam all comments are held for manual green-lighting.

name Remember
email
http://
Message <?>

Quick links

Other people's articles that we think you might be interested in:

Related Amazon links