Here is how lots of people I've talked to conceptualize the relationship between CSS and HTML: you use HTML to structure information in a hierarchical way, and you attach styles to sets of elements, sort of from the outside.
CSS -----------> HTML (styles) "attach" (document)
That's a valid way of looking at it, but it's not the only one. Also valid is the opposite:
CSS <---------- HTML (styles) <verb> (document)
In this view, it's the document that does something to the styles. If you find it hard to see it that way, read on. If it's already totally clear to you, this is your chance to go and read something else.
Caution: this article assumes that you have some programming knowledge.
In more concrete terms
What is the verb in the above diagram? There are multiple names that fit: "use", "call", and "invoke" all work fine. Here is a rough sketch of what that relationship means: The document serves as the input to a list of structural patterns, and it can invoke the style declarations associated with a particular pattern by having a matching structure:
CSS <---------- HTML (pattern) invoke (structure)
Here is a silly example:
CSS
.date { color: #aaa; } .comment .date { font-size: 10px; }
HTML
<div class="comment"> <div class="whatever"> <span class="date">2013-09-10</span> </div> </div>
(Note that this example is not a recommendation for how to write good CSS code or markup.)
And here is how the example translates into patterns and the structure of document fragments:
Patterns:
.date .comment .date
Structure of document fragments (incomplete list):
span div .comment .date div div div div span div span .whatever span .comment .date …
You can imagine the document as being the user of the style sheet who tries to get the parameters right in order to match the interfaces (or patterns) the style sheet exposes. It is analogous to a programmer who wants to use an API and looks up function signatures to find out what the expected arguments are.
Now what's that view useful for?
Learn from analogous models
If the document encodes something analogous to function calls, then things we know about function calls may also be valid for the document/style-sheet relationship.
When designing function signatures, common questions to ask are:
- How much does the function know/assume about its potential calling contexts?
- Are there other valid uses of it than the ones I am considering?
- Can I reduce coupling (between specific use cases and the interface the function provides) by making the arguments less specific?
With the proposed model, you can design a style sheet as if it were a programming interface and ask very similar questions:
- How much do the selectors know/assume about the structure of document fragments?
- Can I think of other user interface elements that would want to use the same styles?
- Can I reduce coupling (between specific use cases and the selector pattern I provide) by making the selector less specific?
A similar design principle you can apply to style sheets is the Law of Demeter or "principle of least knowledge". (It is not really a law by any commonly used definition of "law", but that's what it's called anyway.) Let's look at a few (possibly terrible) selectors and see how much they know about more or less related document fragments:
a) #post-123 b) ul.comments li ul li c) .foo .bar d) .foo.bar e) .tweet > .avatar f) .post hr
Selector a knows about only one value. It's the equivalent of writing a function that only accepts one value:
def seven_times_two(x) if x == 7 14 else nil end end
That's sort of a silly thing to do, but it doesn't violate the Law of Demeter.
Selector b aims to affect some set of list items, but in order to get at them, it takes quite a detour and mentions all kinds of landmarks along the way. Here is some analogous pseudo-code to illustrate that kind of interface:
def styles_for_special_list_item(li) if li.parent(:ul).parent(:li).parent(:ul, :class => :comments) {:color => 'black'} else nil end end
That's clearly an example of a selector/function that violates the principle of least knowledge.
I'll leave the other examples as an exercise for the reader.
Okay, got it. What's next?
After this short tour through overlapping mental models, go and check out some of the suggestions people have made for how to write good CSS code and try to see how they make sense or how you could explain them in different terms if you think of a style sheet as a programming interface:
- OOCSS by Nicole Sullivan
- Block-Element-Modifier (BEM) by Yandex
- Functional CSS (FCSS) by Wealthfront
Also, go back to some code you're working with and answer the interface design questions above.
That's it for now. I am @fronx on Twitter.