DEV Community

Aykut Akgün
Aykut Akgün

Posted on

The weird behaviour of CSS

Question: What is the color of the text?

<div class="parentclass">
  <p class="class1 class2">
    Text
  </p>
</div>
Enter fullscreen mode Exit fullscreen mode
/* 1 */
.class1.class1.class1 {
  color:red
}

/* 2 */
.class1.class2 {
  color:cyan
}

/* 3 */
.class1 {
  color:blue
}

/* 4 */
.class1:hover {
  color:black
}

/* 5 */
.parentclass .class1 {
  color:yellow
}
Enter fullscreen mode Exit fullscreen mode

Spoiler:

Result

Case 1 wins aka the text color is red.


But why is that? and how exactly does CSS behave?
So I decided to open up a Jsfiddle and start playing around. Those are the results I've gotten:

In total, we have 2 rules and a special condition that controls CSS behavior. After that, we dive into my theory on why it works like that?

  1. Css uses something like a weight system which is depending on the number of selectors.

That also explains the behavior why for example

/* This one loses since its got in total 2 selectors,
once the .parentclass and once .class1 */
.parentclass .class1 {
   color:red
}

/* And this one wins since this one has in total 3 selectors */
.class1.class2.class3 {
   color:cyan
}
Enter fullscreen mode Exit fullscreen mode

And if we now add this 3th case, this would win since its got more selector segments in total, even if its always the same Class

.class1.class1.class1.class1 {
   color: blue
}
Enter fullscreen mode Exit fullscreen mode

The Html if you want to test it out:

<div class="parentclass">
  <p class="class1 class2 class3">
    Text
  </p>
</div>
Enter fullscreen mode Exit fullscreen mode

Okay, but what if we have now a case where we got 2 Classes with the same weight?

.class1 {
color: red
}
.class2 {
color: blue
}
Enter fullscreen mode Exit fullscreen mode

In this case, the Text-color would be blue aka .class2 wins. The second rule is that if 2 selectors have the same amount of selectors, the latest one would win.

So TLTR would be:

  1. It sorts by the number of Selectors
  2. It sorts by the latest Selector.

But what about CSS states like hover?

things like :hover or :selected are basically applying to rule 1, and those CSS rules are disabled until the condition, for example hovering over the element is met.

For example

/* This has the selector disabled until 
i hover over it, then it has the selector length of 2*/
.class1:hover {
color: red
}

.class1 {
color: blue
}
Enter fullscreen mode Exit fullscreen mode

But if I apply now the trick on adding the same class over and over to increase the weight the hover state would lose since it has only a selector length of 2.

/* Loses due to rule 2, its written further down in the CSS file*/
.class1.class1 {
color: cyan
}

/* Loses due to rule 1, since the weight here is 3 instead of 2.*/
.class1.class1.class1 {
color: cyan
}
Enter fullscreen mode Exit fullscreen mode

And here is some extraInfo:
The order of the classes on the element or in the css doesnt matter, that means that:
class="class1 class2" is equal to class="class2 class1"
And that:
.class1.class2 is equal to .class2.class1

The one which gets applied in the case above is simply the one that is further down so that means rule 2.

So the question is now: Why? (opinion)

I don't know the exact reasons but if I had to take a guess id say it's a genius system. This is extremely performant since they likely work under the hood with dictionaries or something like that, and by simply counting the number of selectors they basically can obey all the rules without any issues.

And to get the idea to develop it like this is just amazing!

I hope you guys learned something and enjoyed my first blog post. I plan to make more posts while I discover more.

So I wish you a pleasant day!

Top comments (0)