I seem to have a more and more things to complain about CSS lately. In my quest to create overly verbose style sheets, I can't help but to dream up better ways of formatting CSS rules.
CSS rules seem to be modeled after some common programming syntaxes, specifically that of C-influenced languages. These programming languages use 'braces' ('curly brackets,' ’squiggly braces,' and what have you) to define blocks of code (among other uses). In CSS the braces wrap the declaration (or sets of property-value pairs) associated with a selector, all of which combine to make a rule. For clarification’s sake, let’s have an example:
body p:hover { color: #ccc; font-size: 1.1em; }Example 1: Standard CSS rule with selector, and declaration
In this example "color" and "font-size" are properties, and "#ccc" and "1.1em" are values. Combining them, such as "color: #ccc;", creates a property-value pair, of which, there are two in this example and together they make up the declaration. Finally, "body p:hover" is the selector. Put all these elements together as shown makes a CSS rule.
The important bit of the previous example, relative to this writing at least, are the braces. They wrap the complete declaration, signifying the beginning and end of the list of property-value pairs. Theoretically, had the CSS specification been written alternately, we could use the end of a line to delineate the end of the pairs, like so:
body p:hover color: #ccc; font-size: 1.1em;Example 2: Hypothetical CSS syntax without delineating braces
If you're savvy, you'll notice that by removing the braces it becomes increasingly difficult to determine where the selector ends, and where the first pair begins. This is the beauty of the brace.
In CSS the brace only has one job — to encapsulate declarations — however it has the power to do so much more. It could easily be used to enclose just about any CSS information, naturally creating a hierarchy of rule blocks. Take this theoretical CSS structure, for example:
body {
p:hover { color: #ccc; #font-size: 1.1em; }
}Example 3: Theoretical CSS syntax which allows rule nesting
The CSS code above is functionally identical to that in Example 1. Why, then, is this format significant? In CSS a very important, but often overlooked concept is the specificity, or in simpler terms: the weight of a selector. Entire lectures, or whole books could no doubt be assembled on just the topic of specificity alone, but in short, specificity refers to how important a selector is. The more specific a selector, the more weight it has. Selectors with more weight affect elements over selectors with less weight.
In an effort to achieve more specificity, or to cause CSS rules to carry more weight, sometimes stylesheets start to look something like this:
html body div.navigation ul>li { color: red; border: 1px solid blue; }
html body div.navigation ul>li p { color: blue; border: 1px dotted green; }
html body div.navigation ul>li a { color: green; border: 1px dashed red; }Example 4: A very specific, yet inefficient stylesheet
Combined with principles like DRY and the never-ending quest for smaller and quicker file transfers and page renders, it’s clear why this is far from ideal. Arguably there are many ways to remedy a situation like this, and most CSS gurus will probably suggest targeting an ID or class. If you need to target elements without class names or IDs, however, you're still going to end up repeating yourself. This is where nesting shows its power.
html body div.navigation ul>li {
color: red; border: 1px solid blue;
p { color: blue; border: 1px dotted green; }
a { color: green; border: 1px dashed red; }
}Example 5: Hypothetical CSS stylesheet with nested rules
The code in example 5 is functionally identical to that of example 4, each selector with the same specificity, but by nesting child elements (p, a) of the parent selector (ul>li) inside the parent’s declaration, all repetition is eliminated.
Admittedly, this solution isn't perfect. Just like in example 2, it has become more difficult to discern between properties and nested selectors. For example; is "p" the name of a property, to be followed by a value, or the start of a selector? Clever coding coding can easily make this distinction, but it’s yet one more thing the browser must worry about. It’s not all bad, though. In comparison to the previous, example 5 is lighter (smaller file size), more organized, and more readable. Unfortunately, it’s also not backward compatible.
He who moves not forward, goes backward
Johann Wolfgang von Goethe