This is a very good question. Everywhere I look, CSS files tend to get out of control after a while - especially, but not only, when working in a team.
The following are the rules I am myself trying to adhere to (not that I always fully manage to.)
Refactor early, refactor often. Frequently clean up CSS files, fuse together multiple definitions of the same class. Remove obsolete definitions immediately.
When adding CSS during fixing bugs, leave a comment as to what the change does ("This is to make sure the box is left aligned in IE < 7")
Avoid redundancies, e.g. defining the same thing in .classname
and .classname:hover
.
Use comments /** Head **/
to build a clear structure.
Use a prettifier tool that helps maintain a constant style. I use Polystyle, with which I'm quite happy (costs $15 but is money well spent). I'm sure there are free ones around as well (Update: like for example Code Beautifier based on CSS Tidy, an open-source tool I've not used myself yet but looks very interesting.)
Build sensible classes. See below for a few notes on this.
Use semantics, avoid DIV soup - use <ul>
s for menus, for example.
Define everything on as low a level as possible (e.g. a default font family, colour and size in the body
) and use inherit
where possible
If you have very complex CSS, maybe a CSS pre-compiler helps. I'm planning to look into xCSS for the very same reason soon. There are several others around.
If working in a team, highlight the necessity of quality and standards for CSS files as well. Everybody's big on coding standards in their programming language(s), but there is little awareness that this is necessary for CSS too.
If working in a team, do consider using Version Control. It makes things that much easier to track, and editing conflicts that much easier to solve. It's really worth it, even if you're "just" into HTML and CSS.
Do not work with !important
. Not only because IE =< 7 can't deal with it. In a complex structure, the use of !important is often tempting to change a behaviour whose source can't be found, put it's poison for long-term maintenance.
Building sensible classes
This is how I like to build sensible classes.
I apply global settings first:
body { font-family: .... font-size ... color ... }
a { text-decoration: none; }
Then, I identify the main sections of the page's layout - e.g. the top area, the menu, the content, and the footer. If I wrote good markup, these areas will be identical with the HTML structure.
Then, I start building CSS classes, specifying as much ancestry as possible and sensible, and grouping related classes as closely as possible.
div.content ul.table_of_contents
div.content ul.table_of_contents li
div.content ul.table_of_contents li h1
div.content ul.table_of_contents li h2
div.content ul.table_of_contents li span.pagenumber
Think of the whole CSS structure as a tree with increasingly specific definitions the further away from the root you are. You want to keep the number of classes as low as possible, and you want to repeat yourself as seldom as possible.
For example, let's say you have three levels of navigational menus.
These three menus look different, but they also share certain characteristics. For example, they are all <ul>
, they all have the same font size, and the items are all next to each other (as opposed to the default rendering of an ul
). Also, none of the menus has any bullet points (list-style-type
).
First, define the common characteristics into a class named menu
:
div.navi ul.menu { display: ...; list-style-type: none; list-style-image: none; }
div.navi ul.menu li { float: left }
then, define the specific characteristics of each of the three menus. Level 1 is 40 pixels tall; levels 2 and 3 20 pixels.
Note: you could also use multiple classes for this but Internet Explorer 6 has problems with multiple classes, so this example uses id
s.
div.navi ul.menu#level1 { height: 40px; }
div.navi ul.menu#level2 { height: 20px; }
div.navi ul.menu#level3 { height: 16px; }
The markup for the menu will look like this:
<ul id="level1" class="menu"><li> ...... </li></ul>
<ul id="level2" class="menu"><li> ...... </li></ul>
<ul id="level3" class="menu"><li> ...... </li></ul>
If you have semantically similar elements on the page - like these three menus - try to work out the commonalities first and put them into a class; then, work out the specific properties and apply them to classes or, if you have to support Internet Explorer 6, ID's.
Miscellaneous HTML tips
If you add these semantics into your HTML output, designers can later customize the look of web sites and/or apps using pure CSS, which is a great advantage and time-saver.
If possible, give every page's body a unique class: <body class='contactpage'>
this makes it very easy to add page-specific tweaks to the style sheet:
body.contactpage div.container ul.mainmenu li { color: green }
When building menus automatically, add as much CSS context as possible to allow extensive styling later. For example:
<ul class="mainmenu">
<li class="item_first item_active item_1"> First item </li>
<li class="item_2"> Second item </li>
<li class="item_3"> Third item </li>
<li class="item_last item_4"> Fourth item </li>
</ul>
This way, every menu item can be accessed for styling according to its semantic context: Whether it's the first or last item in the list; Whether it's the currently active item; and by number.
Note that this assigning of multiple classes as outlined in the example above does not work properly in IE6. There is a workaround to make IE6 able to deal with multiple classes; I haven't tried it yet but looks very promising, coming from Dean Edwards. Until then, you will have to set the class that is most important to you (item number, active or first/last) or resort to using IDs. (booo IE6!)