css specificity pt2 / lacking proximity

In last week's article on fuzzy css specificity I presented a case that illustrated the difference between regular specificity and css specificity. While it's interesting to review these cases, it's even better to get to the very core of them. This article will do just that.

abstract case: where am I

Real-world case: I'm standing on this Earth, in Belgium, in Antwerp, in Central Park
Translated to css: .planet#Earth .country#Belgium .city#Antwerp .park#Central me

Before starting, let's consider this little abstraction of the issue we're dealing with. Throughout the article I'm going to use the above case to illustrate the difference between regular specificity and css specificity. It's a real world case easily translated to css, describing my current position on this very planet. I've used classes for generic concepts and ids for unique instances of these concepts.

specificity

Specificity is about eliminating options. Making a description more specific will eliminate the chance of error and misunderstanding. It's like a game of darts, where you try to hit the bulls eye. The concept was introduced in css because certain elements in the DOM could be targeted by multiple css rules. When the same property is defined in two separate css rules, specificity helps to determine which property will win the battle for dominance.

#Belgium me {...} .country me {...}

When they developed css they tried to mimic regular specificity as much as possible, but they hit a few problems along the way. In simple cases though, it works just as expected. By using ids and classes they managed to come close to what we would logically expect. In the example above, the the first rule is more specific than the second because the id marks a unique instance of the class, meaning what is targeted by the id should be more specific, which is obviously the case.

This is the basic idea of css specificity, but it lacks one major aspect that regular specificity has.

proximity

.city .park me {...} .planet .country me {...}

Consider the code above. In css, both rules have an equal weight because they both contain two classes. Because the second rule appears last it wins the battle of dominance. In the real world though, the first rule is considered to be more specific. It tells you I'm in a city park, the second rule only states I'm in country on this planet. Let's look at another example:

.country #Antwerp me {...} #Belgium .city me {...}

Again, in css both rules have an equal weight because they both contain a class and id. In the real world , the fact that the first rule uses an id for city creates a greater specificity than when the id is used for country. And one final example:

.planet .country me {...} .city me {...}

This example shows the problem is bigger than simply the order of our css statements. While the first rule appears to be more specific in css, in the real world the second rule would be considered the most specific of the two, as it manages to put a bigger limitation on my whereabouts.

What's lacking in css is the concept of proximity. The css language doesn't care how close (in the DOM) a class, id or html element is to "me", it merely sees how many of each are in a selector and computes a weight. Contrary to our everyday world, where proximity is pretty much crucial to determine the specificity of something.

time for revolution

So is css failing us? To truly answer this question we should work out a full model where proximity would be introduced in css. This is a bit too complex to do right away, but my gut feeling tells me that including (DOM) proximity would make things way more complicated. While it would probably be possible to create rules that lie closer to our own mental model of specificity, the clarity and ease of understanding of the current css model would probably be lost.

Maybe I'm wrong though, and some form of proximity could be easily included without completely messing things up, but that I'll leave to greater minds than myself. As for now, the issues that arise seem smaller than the trouble to go and change this core concept of the css language.

conclusion

Know that css specificity is different from what we normally understand when talking about specificity. I personally try to avoid the term specificity when dealing with css. I'd rather use "weight" to talk about selectors, as it comes closer to how it actually works in css. It doesn't make much of a difference, and from time to time I still find myself forgetting about the difference between both, but knowing where the exact difference lies surely helped me in conquering this pretty common mistake.