Which brings me back to my original question: is there a set of rules to follow to correctly override a parent theme’s CSS with the child theme’s CSS, or is it mostly just mucking around until you figure it out?
Okay. Here’s the quick rundown on CSS Sanity.
My understanding is that in a CSS document, the CSS is read from top to bottom, with the rules being executed in that order, so rules beneath are higher priority
This is the first thing you have to unlearn: Order doesn’t matter. ALL CSS is active ALL the time. Doesn’t matter what order they are in the HTML. Doesn’t matter if it’s in a child theme or not. Yes, okay, order does actually matter in the way you say, but for the purpose of maintaining your sanity, stop thinking that way. Pretend that order quite literally does not matter, at all, ever.
Once you have that down, then you can understand specificity.
More specific rules override less specific ones. It’s not a guessing game. This has a defined hierarchy.
Highest to lowest:
1. Inline styles. An inline style is in the HTML itself, in the “style” part of the tag. h1 style=“color: #fff;”
2. IDs. These are in the id=”” of the tag, and referred to in the CSS by hashtags: #element.
3. Classes (also attributes and pseudo-classes). Anything in a “class”, gets referred to with the period, like .element. Attributes like [attr] and pseudo-classes like :hover, :focus have the same value.
4. Elements and pseudo-elements. These are things like “div” or “ul” in CSS. Direct references to elements in the page. Pseudo-elements are at the same level. These would be elements that would be there if they were not pretend, like :before and :after.
If you prefer to do it in actual math, you can calculate a value for any given rule with something like a points based system. 1000 points for the inline styles, 100 points for IDs, 10 points for classes, 1 point for elements. So a rule like this in the CSS body #content .data img:hover
gets 122 points. One ID (content), 2 classes (data and hover), 2 elements (body and img). A rule scoring higher referring to the same thing in the HTML would win and have precedence.
But, realistically, you just need to learn what is more specific. “body” refers to literally anything on the page. “body img” only refers to the images on the page. If you had both “body” and “img” as selectors in your CSS, then they have the same score, but “img” is more specific to actual images than the “body” is because, well, they’re using actual img tags directly.
If you need to override a style rule, use a more specific selector. Doesn’t matter where it is in terms of order on the page, more specific always wins, because all selectors available are applied all the time. Order only matters when you use the same identical selectors for the same identical rules, which you probably shouldn’t do because that way lies madness.
Also, “!important” beats non-“!important”. Avoid using this unless you have no other choice.
But let’s say I only want odd row moderator posts to have a black moderator badge background. There isn’t a CSS rule for that in the parent theme, so maybe I would do something like this:
Avoid adding things to the HTML like “odd” and “even” classes, when CSS has native support for such things to begin with. If you’re modifying the HTML just to add classes for CSS targeting, then you’re probably doing-it-wrong. CSS is powerful. Use it natively.
.author-badge-moderator:nth-child(odd) { ... }
Or something similar. Maybe you need the odd divs above it and then want to target the moderator badge inside them. So with html like:
<div class="example">
<span class="author-badge-moderator"></span>
</div>
... repeating...
Then something like this instead:
.example:nth-child(odd) .author-badge-moderator { ... }