4

I need to style the text in all elements of a HTML document except the ones nested in a specific class. I have no control over the HTML, I can only modify the CSS.

Here is a piece of code:

<div class="container">
  <div class="column c1">
    <div class="text">
      text in column 1
    </div>
  </div>
  <div class="column c2">
    <div class="text">
      text in column 2
    </div>  
  </div>
  <div class="column c3">
    <div class="text">
      text in column 3
    </div>  
  </div>
</div>

I want all text elements, except the ones in a c1 element, to be bold. I don't know in advance how many columns there can be.

I've tried the following CSS that makes use of the :not selector, but it renders everything bold:

.container {
  display: flex;
}

.column {
  padding: 0 1em;
}

:not(.c1) .text {
  font-weight: bold;
}

Why isn't the :not selector working? What am I doing wrong? Here is a jsfiddle to try out.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Lucio Crusca
  • 1,277
  • 3
  • 15
  • 41

4 Answers4

8

See here. You have to declare the column class.

This does the job:

.column:not(.c1) .text {
  font-weight: bold;
}
Carle B. Navy
  • 1,156
  • 10
  • 28
  • Although it should be noted that the reason why `:not(.c1) .text` doesn't work is that, according to [MDN](https://developer.mozilla.org/en/docs/Web/CSS/:not), `:not(foo){}` will match anything that isn't foo, **including `` and ``**, so it will match `.container .text`, `html .text` and `body .text`. – Khaled Mashaly Feb 20 '17 at 20:20
4

You simply need to switch from a descendant to a child combinator.

In other words, from this:

:not(.c1) .text 

To this:

:not(.c1) > .text 

revised fiddle


Your selector...

:not(.c1) .text {
  font-weight: bold;
}

is equivalent to this:

*:not(.c1) .text {
  font-weight: bold;
}

This selector says:

select an element with class text that is a descendant of any other element, except an element with class c1.

Okay, well, .text is a descendant of a div with class c1 in one instance – so it gets excluded as you intend. But .text is also a descendant of html, body and .container. So the rule fails to work as you expect because it satisfies multiple scenarios.

Instead, try this:

:not(.c1) > .text {
  font-weight: bold;
}

This selector says:

select an element with class text when the parent element does not have the class c1.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
4

That's because :not(.c1) will select any element that doesn't have that class. That can be the .container too.

Either add a direct child combinator:

:not(.c1) > .text {
  font-weight: bold;
}

Or use the other class as well:

.column:not(.c1) .text {
  font-weight: bold;
}
pol
  • 2,641
  • 10
  • 16
-2

This can work too :

 .column:not(.c1) .text {
      font-weight: bold;
  }
Cawet
  • 254
  • 2
  • 12
  • 1
    That's nonsense. A pseudo-class *is* a selector. A pseudo-class is a simple selector, just like an id selector or a class selector or a type selector. And therefore a pseudo-class *can* be used alone, without having to be qualified with any other simple selector. – BoltClock Feb 21 '17 at 03:50
  • damned ! the fact that it's working too if you simply add a selector before totally measled me. Thank's for correcting me – Cawet Feb 21 '17 at 14:29