ID: I202610031345
Status: idea
Tags: CSS

css specificity

I was wondering, why does my css listen to the 1st rule instead of the 2nd one, the 2nd tone looks more specific:

#main > section {
	margin-bottom: 1rem;
}
section.portfolioGallerySection.no-bottom-margins {  
	margin-bottom: 0;  
}

Turns out, it’s because css counts differently than I thought.

This is a CSS specificity issue. Specificity is counted as (IDs, classes/attributes/pseudo-classes, elements):

  • #main > section → (1, 0, 1): one ID (#main) and one element (section). The > combinator adds nothing.
  • section.portfolioGallerySection.no-bottom-margins → (0, 2, 1): two classes and one element. Specificity is compared column by column, left to right. A single ID beats any number of classes, so the first rule wins even though the second has more classes.

Solution:

/* Option 1, just add the #main as well */
#main > section.portfolioGallerySection.no-bottom-margins {
  margin-bottom: 0;
}
 
/* Option 2, exclude #main from specificity with :where() */
:where(#main) > section {
  margin-bottom: 1rem;
}

In the 2nd option, :where() counts as zero specificity, so this rule becomes (0, 0, 1), and your .no-bottom-margins rule wins with no other changes. Why this works like that, I have no clue.


References