2

Is it possible to apply certain CSS to any element, except descendants of a certain class?

Here's a fiddle: http://jsfiddle.net/68jgdthm

As you can see I want everything on the page to be dark except elements which are descendants of the light class. The trick here is that one can't know if the element is a direct descendant, e.g. it might be this:

<div class="light">
  <p>Element</p>
</div>

but it might also be this:

<div class="light">
  <div>
    <div>
      <p>Element</p>
    </div>
  </div>
</div>

The dark class is almost always added to the body element and will always be a parent of any light classes.

One might say:

  • Just make the body "light" and add dark classes to any elements you need. - But I actually need the opposite, I need everything to be dark and certain elements to be light.

  • Then add "light" styles and add the light class to elements you need. - I already have the dark styles, so I'm looking for an easier "excluding" solution (I'm using LESS, so prefixing etc. is quite easy).

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Tony Bogdanov
  • 7,436
  • 10
  • 49
  • 80

2 Answers2

2

Color is an inherited property. Therefore just by declaring .dark and .light to have the wanted color is a good thing. You can make a default by assigning it to the body. I think atomic design like this is a good practice, as you don't add too much specificity in your CSS.

You could do this:

body {
    color: #ccc;
}
.dark {
    color: #000;
}
.light {
    color: #fff;
}

Demo: http://jsfiddle.net/68jgdthm/1/

Sampsa
  • 701
  • 1
  • 5
  • 18
  • Yes, I know, but that is exactly the thing I'm trying to avoid - writing redundant code. – Tony Bogdanov Jan 03 '15 at 11:40
  • Why is this redundant? –  Jan 03 '15 at 11:58
  • @Sampsa Why do you need `*` since `color` is inherited? –  Jan 03 '15 at 11:59
  • 1
    @torazaburo: That's what I thought as well. In the end, when writing my answer I decided not to assume that `color` was the only property the OP had to deal with. – BoltClock Jan 03 '15 at 12:04
  • It isn't redundant if it does the job you want done! – GuyH Jan 03 '15 at 12:29
  • Yup, the `*` is not needed. It was just to clarify that these things inherit. I think atomic design like `.dark` and `.light` are good, and that's why I said it was a bit nasty. I edited my answer to be more clear. – Sampsa Jan 03 '15 at 16:04
2

You will not be able to exclude descendants this way without writing a separate selector. You won't be able to do this even using :not(), for the reasons stated here.

Fortunately, the fact that .light elements will only ever occur within the context of a .dark element and not vice versa makes this a little easier. Since you have a body CSS rule already, just add .light p to that rule, and move the entire ruleset underneath .dark p so .light p will take precedence:

.dark p {
    color: #000;
}

body, .light p {
    color: #ccc;
}

Updated fiddle

Alternatively if you want to keep the body rule on top, you could bump up the specificity of .light p to ensure it will take precedence:

body, body .light p {
    color: #ccc;
}

.dark p {
    color: #000;
}
Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Your solution is good, although I will still have to "write" separate declarations for the `light` and `dark` styles, since `p` usually has it's own styles for the light version, which aren't just inherited from the `body`. At least now I know why it wasn't working. – Tony Bogdanov Jan 03 '15 at 12:03