Reputation: 12549
I have widget that has some styling applied to it. But then if a certain class is applied to the body that styling gets overridden. For example, let's say the body gets a class of .blue-theme
.widget { background: lime }
body.blue-theme .widget { background: blue }
This override will obviously apply to all widgets. Now let's say there's a type of page called body.test
, where the same rules apply except for one widget, that has a class of .joe
. This .joe
widget can appear on other pages - but only if it appears on the body.blue-theme.test
page does it ignore the overriding styles. I can achieve by overriding it again like this:
.widget { background: lime }
body.blue-theme .widget { background: blue }
body.blue-theme.test .widget.joe { background: lime } // revert to original styling
However in my case, I have many styles applied to the widget and it's child elements, so much so that it would be a huge headache if I need to make a change and have to change the styling in two places.
Is there some way, perhaps with clever use of selectors, whereby I can do this without that extra third line in my example? For example; saying that I want to override any widget in body.blue-theme
, except for .widget.joe
if the body also has a class of .test
.
I am using LESS CSS, so a technique using that would be fine.
Upvotes: 1
Views: 302
Reputation: 724342
If :not()
allowed combinators, this would be trivial:
.widget { background: lime }
body.blue-theme .widget:not(body.test .joe) { background: blue }
But it doesn't in CSS, and there is no equivalent for :not(body.test .joe)
that can be expressed as a single valid selector.
In your case, since body.blue-theme.test .widget.joe
is more specific than body.blue-theme .widget
, it is sufficient to move that selector into your first ruleset. It will override the second ruleset for those particular elements:
.widget, body.blue-theme.test .widget.joe { background: lime }
body.blue-theme .widget { background: blue }
Alternatively you could have two separate selectors in the overriding rule, one for all widgets in body.blue-theme:not(.test)
, and one for all widgets except .joe
in body.blue-theme.test
:
.widget { background: lime }
body.blue-theme:not(.test) .widget,
body.blue-theme.test .widget:not(.joe) { background: blue }
Either way, you will require at least two selectors in one of the rulesets. Personally, I find this method needlessly verbose compared to just combining the first and third rulesets together.
Upvotes: 1
Reputation: 30999
This will do the job:
body.blue-theme.test .widget:not(.joe) { background: "blue" }
Upvotes: 2