CSS for Programmers (and anyone else who appreciates clean, approachable CSS)
When used properly CSS can be an elegant and efficient way to express the presentational rules for a web page. Programmers typically love and embrace tools that provide for separation of concerns, as this is often the best method of managing complexity. So it’s strange to me that some of the most bloated, mangled and unmaintainable CSS I’ve ever seen was written by programmers. I might expect this type of behavior from designers/illustrators, but come on, not Ruby on Rails programmers–a group of people willing to accept subpar raw-performance for improvements in code architecture and readability (myself included) should be all over this CSS stuff.
Now, I should explain that CSS is only one of many tools the proficient web developer should employ for separating concerns and managing complexity. Great CSS starts with clean, well-structured (X)HTML markup. And so I present this very good, very general guide to clean HTML markup via Digg. The most important bullet points for our discussion are:
- Clean, Semantic Markup Structure.
- Before you use the div or span tag, ask yourself why? Is this content better suited for a header, paragraph, table, block quote, code block (code and pre tags), ordered/unordered/dictionary list or some other esoteric HTML tag I’ve left out?
- Semantically Justified
idandclassNames- Spans containing daily changes in stock price should be given class names like
gainandloss, notgreenandred. - Data related to how a piece of information should be displayed is best reserved for CSS.
- Spans containing daily changes in stock price should be given class names like
- and of course, No Styling!
As an added bonus your rails, php, python, asp, whatever code will benefit from cleaner (X)HTML markup. A mess of divs is just as bad as table-based layouts–but I think most web programmers readily understand this because their code does interact so directly with the HTML structure.
Really Good CSS
There are three main goals I try to accomplish when writing CSS rules:
- Elements should be targeted in a meaningful way.
- Pieces of the page which look alike should be styled with one CSS rule.
- The location of a rule in the CSS document should reflect it’s specificity.
Targeting Elements in a Meaningful Way - Variable/Method Naming for CSS
Already, clean, well-structured (X)HTML will start to pay off. Choosing id name’s and class name’s is like choosing variable names. So, structuring CSS rules is like considering how method and variable names will interact to construct meaningful expressions. Let’s look at a short excerpt of HTML from a typical blog:
<body>
.
<a href="http://niqos.com>this blog</a>
.
<div class="entry-body">
<p>Lorem <a href="http://google.com">Ipsum</a> dolor.</p>
</div>
.
.
.
</body>
Let’s say you’d like to make the hyper-links within the blog post green. You could write:
body div p a {
color:green;
}
This will certainly work. And in a sufficiently simple site, you may never have another occurrence of links within paragraphs within divs; it’s left as an exercise for the reader to derive significantly simple enough examples to discredit me. An improvement would be to take advantage of your semantically significant class naming.
div.entry-body p a {
color:green;
}
We can drop the body tag from the rule because it doesn’t add anything. By the same logic, we should drop the p tag.
div.entry-body a {
color:green;
}
This combination gives us the most meaningful, readable CSS rule. “Links within entry bodies should appear green.”
Styling Like Elements with a Single Rule - DRY for CSS
It’s always a bad idea to replicate functionality in multiple places within a single piece of software. The same goes for CSS. Take for example the header section of this very blog. On the other pages of the site I wanted the logo to be contained in an h1 tag, indicating the highest level of semantic significance. But on pages like this one (blog posts) I wanted the logo to be contained in an h2 tag, deferring the highest level of semantic significance to the blog post title. The markup goes something like this:
Blog Post Pages:
<div id="header">
<h2 id="logo">niqos design studio</h2>
</div>
All of the Other Pages:
<div id="header">
<h1 id="logo">niqos design studio</h1>
</div>
So I write my CSS rules:
h1#logo {
margin:...;
padding:...;
background:...;
}
h2#logo {
margin:...;
padding:...;
background:...;
}
Great, they look the same. The issue is that I’m repeating functionality in two distinctly different locations. The astute reader will have already thwarted my poorly contrived error with the following:
h1#logo , h2#logo {
margin:...;
padding:...;
background:...;
}
Locked into beautiful, perpetual imitation. Notice how I didn’t even need to specify div#header h1#logo. Since id name’s are unique I know that there will never be another element with the id of logo. By the same logic you could say that I only needed to specify #logo without the h1 and h2 tags. Good point. This is where you must exercise discretion. I started off by writing this rule using just #logo, but because of the browsers default text size for varying levels of header elements, my rule worked properly when the logo was in an h1 but not an h2. So I wrote the rule in a way which reminded me that it applied both to h1 and h2 elements.
Now, two (or more) elements don’t have to appear exactly the same in the page to make use of this technique. Let’s say the layout was slightly different on blog post pages and so I wanted the logo to appear slightly further from the top. I might write:
h1#logo , h2#logo {
margin:...;
padding:...;
background:...;
}
h1#logo {
margin-top:30px;
}
Similar styles are held within a single rule while slight variations are specified later in the style sheet.
The Location of a Rule in the CSS Document Should Reflect it’s Specificity
At this point your probably reflecting on the quality of my segue into this third and final section. Please hold your applause.
The concept of the ‘cascade’ in CSS is particularly well-served by organizing your CSS document in such a way that the most specific rules come last. In CSS, ‘specificity’ is a very ‘specific’ term with a whole set of ‘specifications’ about how a certain CSS rule takes precedence over others which refer to the same item in the page.
When I write CSS, I try to avoid thinking about this. There’s a whole system for calculating the weight of a given CSS rule, but in practice I find it’s best not to rely on, or worry about, specificity. And it’s not just laziness, CSS rules which may be “over-specified” (you could get away with writing less verbose rules that do the same thing) but which take advantage of semantically meaningful id names and class names are more readable.
Of course there are times when you will write two rules with the same “specifity” value without even realizing it. So to further avoid thinking about specificity and avoid this potentially ambiguous case (at least until you start calculating values), it’s a good idea to put the rules which you recognize semantically as most specific last. Remember this example?
h1#logo , h2#logo {
margin:...;
padding:...;
background:...;
}
h1#logo {
margin-top:30px;
}
Both rules have the same “specificity” value, but intuitively you know that the second rule should take precedence, overwriting any margin-top applied in the first. If the order of these rules was reversed, the h1#logo rule could be overwritten. The firebug add-on for Firefox is really invaluable for diagnosing these types of CSS bugs.
CSS isn’t so Bad, is it?
I hope I was able to shed some light on some general CSS best-practices (in my opinion) for programmers with much better things to do than think about CSS. Feel free to drop some suggestions in a comment or two. I think the separation of concerns which CSS helps to enforce is something any good programmer can appreciate.
EDIT: I found a pretty cool rails plugin which is aimed at providing a DRY syntax for writing CSS. I haven’t tried it out at all, but it looks interesting.
Comments
No comments have been made. post comment