The web community is generally coming (or has come) to accept that ’semantic’ class naming conventions (’old school’ elements with classes describing content not appearance) are preferable to the 'boldGreyLink' type conventions popular around the millennium.
| Millenium era HTML & CSS | ‘Semantic’ era HTML & CSS |
|---|---|
<html> <head> <title>'Millenium' era</title> <style type="text/css"> div.redSubHead { color: red; } p.greyText { color: #666; } td.columnHeaderCell { font-weight: bold; } td.oddRowCell { background: #eee; } td.evenRowCell { background: #ddd; } </style> </head> <body> <div class="redSub">sub 1</div> <p class="greyText">blah</p> <table> <tr> <td class="colHeader">A</td> <td class="colHeader">B</td> </tr> <tr> <td class="oddRow">1</td> <td class="oddRow">2</td> </tr> <tr> <td class="evenRow">3</td> <td class="evenRow">4</td> </tr> </table> </body> </html> |
<html> <head> <title>'Semantic' era</title> <style type="text/css"> .section h2 { color: red; } .section p { color: #666; } .section thead th { font-weight: bold; } .section td { background: #ddd; } .section tr.odd td { background: #eee; } </style> </head> <body> <div class="section"> <h2>sub 1</h2> <p>blah</p> <table> <thead> <tr> <th>A</th> <th>B</th> </tr> </thead> <tr class="odd"> <td>1</td> <td>2</td> </tr> <tr> <td>3</td> <td>4</td> </tr> </table> </div> </body> </html> |
|
|
One pillar of the ’semantic’ technique is the sparing application of class attributes, primarily to container elements. Elements are ‘caught’ using CSS ‘descendant’ selectors (multi-part) which target hierarchies rather than using simple class selectors which require a directly applied class attribute. Using descendant selectors respects the hierarchical nature of the DOM but makes writing bulk CSS quite tricky. Why? Mainly because CSS stylesheets (and style blocks) are fundamentally rule lists, but the DOM elements which our descendent selectors target are obviously trees. How do we bridge the gap between these fundamentally different structures?
Enter ‘ragged’ CSS
In 2006 I (then a contracting developer) found myself filling the shoes of a fantastic design contractor whose contract was up but sadly not extended (project managers eternally underfund and misunderstand UI). I was the new ‘CSS guy’ for a project with scores of developers, hundreds of pages and crippling compatibility/accessibility requirements. I wasn’t really qualified for the task, but my predecessor gave me a CSS tip that got me through: “don’t sweat the properties, focus on rule hierarchies”.
This rule-centric approach is most clearly evident in the CSS formatting style I picked up on that project and used ever since; a style I call ‘Ragged CSS‘.
| ‘tall’ CSS | ‘ragged’ CSS |
|---|---|
.section h2 {
color: red;
}
.section p {
color: #666;
}
.section thead th {
font-weight: bold;
}
.section td {
background: #ddd;
}
.section tr.odd td {
background: #eee;
}
|
.section { }
.section h2 { color: red; }
.section p { color: #666; }
.section table { }
.section thead th { font-weight: bold; }
.section td { background: #ddd; }
.section tr.odd td { background: #eee; }
|
It differs from the common ‘tall’ CSS formatting style in only a few (primarily cosmetic) ways:
- One line per rule, one rule per lineThere may be hundreds of rules, but each will only have a handful of properties.
- Indent CSS rules to represent target element hierarchyA block of markup (e.g. a calendar) will typically involve several rules (perhaps dozens). Indenting rules more clearly indicates how their properties will cascade.
- Make rules for ‘landmark’ elements (empty rules if necessary)Adding an empty rule for element’s whose classes are used in subsequent selectors makes indentation hierarchy far clearer (improves readability).
- ‘namespace’ your rules to avoid conflictClass names may be repeated on large projects unintentionally. Target ‘abc’ class elements inside ‘xyz’ class elements using a ‘.xyz .abc’ selector rather than a global ‘.abc’ selector to avoid tainting someone else’s unrelated ‘abc’ class.
-
Avoid element prefixes sparingly in your selectorsDon’t use a
'span.content'selector where a plain'.content'selector will do. Dogmatic prefixing (i.e. increasing specificity unnecessarily) makes your rules unnecessarily vulnerable to otherwise inconsequential markup changes (changing thespanto adivfor instance).
I’ve been using this formatting style for a few years now and it’s made complex CSS development a snap (browser quirks aside). If you’re writing ‘tall’ CSS (or using a tool which generates it), give ragged CSS a go on your next project. Your future self (and/or your successor) will thank you for it!