I have a .card
component with two variants:
.card {
padding: 2rem;
border: 2px solid black;
&.is-dark {
background: #151515;
p {
color: white;
}
}
&.is-light {
background: #fcfcfd;
p {
color: #111;
}
}
}
<div class="card is-light">
<p>Some content</p>
<div class="card is-dark">
<p>Some sub-content</p>
</div>
</div>
<hr />
<div class="card is-dark">
<p>Some content</p>
<div class="card is-light">
<p>Some sub-content</p>
</div>
</div>
But as visible in the snippet, for both <p>
, the matching selectors are .card.is-dark p
and .card.is-light p
and the second wins as it is the last, while I’d expect text to be white in the .card.is-light .card.is-dark p
case.
Is there any chance I could tell my CSS to match the deepest in DOM in priority?
I thought of
.card {
&.is-dark {
&, :not(.is-light) {
}
}
}
but it wouldn’t work since it would be the is-dark
that would apply while I’d expect the .is-light
(in the case of .is-light
within .is-dark
).
3
Answers
If you limit your css so that it just targets the direct children then your approach works.
Obviously this has to be adapted, depending on how your actual card HTML will look like, I assume this is a dumbed down version of it. Maybe you can work with an additional wrapper to specify the content of a card for CSS selectors.
Use CSS variables and inheritance will do the right job for you.
Actually you don’t really need variables
You can fix that by using
> p
, but CSS custom properties can become really handy for such situations and result in a – imho – cleaner solution.For
.card.is-dark
and.card.is-light
, you can specify what values the properties should have, and you can then just use those on the elements you want to use.