Using CSS :not with concatenated classes (.row.heading)

135 Views Asked by At

I'm trying to style all div elements except those in two different class groups. Everything I've tried doesn't seem to work.

The below test code should make the div with "test" text content be orange, but none of the selectors work.

div {
  height: 40px;
  width: 100px;
  background: cyan;
  display: inline-block;
}
div:not(.ZoomBar):not(.row.heading) {
  background: orange;
}
div:not(.ZoomBar, .row.heading) {
  background: orange;
}
div:not(.ZoomBar),
div:not(.row.heading) {
  background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div>Test</div>

3

There are 3 best solutions below

4
On BEST ANSWER

The problem with :not() is that it only allows one simple selector at a time. This means any of :not(div), :not(.ZoomBar), :not(.row) and/or :not(.heading). It does not accept either

  • a compound selector, .row.heading, which consists of two class selectors; or
  • a comma-separated list of multiple selectors, .ZoomBar, .row.heading.

It's worth noting however that the selectors you've tried will work in jQuery, though not CSS.

Your problem is compounded (heh) by the fact that you're looking for both kinds of exclusions in a single rule. But it's still doable; it simply means you'll need to write a slightly more convoluted rule, with two selectors to account for the two class selectors in .row.heading:

div {
  height: 40px;
  width: 100px;
  background: cyan;
  display: inline-block;
}
div:not(.ZoomBar):not(.row),
div:not(.ZoomBar):not(.heading) {
  background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div class="heading row">Heading</div>
<div class="heading foo row">Heading</div>
<div class="heading">Heading</div>
<div>Test</div>

If these are the only possible combinations of class names, you might be able to get away with simply excluding div elements with a class attribute using div:not([class]), but based on your question I suspect that this isn't the case.

For instance, notice in the above snippet that the div[class="heading"] element matches div:not(.ZoomBar):not(.row), and is therefore colored orange. If you may have elements with either class name but not both, those elements will be accounted for.

4
On

You can use something like this

You cannot add unfortunately multiple class in a single not selector.

div {
  height: 40px;
  width: 100px;
  background: cyan;
  display: inline-block;
}

 

div:not(.ZoomBar):not([class="row heading"]){
  background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div class="heading">Heading</div>
<div>Test</div>

6
On

The answer is this:

div {
  height: 40px;
  width: 100px;
  background: cyan;
  display: inline-block;
}
div:not([class*="ZoomBar"]):not([class*="row heading"]):not([class*="heading row"]) {
  background: orange;
}

https://jsfiddle.net/ars9fL56/5/