Mayur Koshti Mayur Koshti - 5 months ago 8
CSS Question

:not() selector not selecting element

I have the following string and I want to ignore just strong tag from the string using css selector:

<p><strong>Local:</strong><br>
-Brasília/DF </p>


I tried the following syntax but it doesn't work.

p:not(strong)


Where am I wrong?

Answer

A pseudo-class, attached to an element p:not(strong), selects from those elements to which it is 'attached' (here the p); and a <p> element is always not a <strong> element; therefore this selector will always match every <p> element.

You seem to be trying to style the parent <p> element based on its child <strong> element which cannot work, as CSS has no parent-selector (see: "Is there a CSS parent selector?")

You could, instead, add a class (or other attribute) to the <p> element, and use that in the selector:

<p class="hasStrongDescendant"><strong><strong>Local:</strong><br>
-Brasília/DF </p>

And style with:

p:not(.hasStrongDescendant) {
    /* CSS here */
}

p:not(.hasStrongDescendant) {
  color: orange;
}
<p>A paragraph with no child elements</p>

<p class="hasStrongDescendant"><strong>Local:</strong>
  <br>-Brasília/DF</p>

Or, using a data-* attribute:

<p data-hasChild="strong"><strong>Local:</strong><br>
-Brasília/DF </p>

And style with:

p:not([data-hasChild="strong"]) {
    /* CSS here */
}

p:not([data-hasChild="strong"]) {
  color: #f90;
}
<p>A paragraph with no child elements</p>

<p data-hasChild="strong"><strong>Local:</strong>
  <br>-Brasília/DF</p>

Also, if you wrapped the contents of the <p>, following the <strong>, inside their own element you could style the descendants of the paragraph using the negation selector:

<p>A paragraph with no child elements</p>

<p><strong>Local:</strong>
  <br><span>-Brasília/DF</span>
</p>

Styling with:

p :not(strong) {
  /* note the space between the
     'p' and the ':not()' */
  color: #f90;
}

p :not(strong) {
  color: #f90;
}
<p>A paragraph with no child elements</p>

<p><strong>Local:</strong>
  <br><span>-Brasília/DF</span>
</p>

Two further approaches, assuming that you want to style the text of the child outside of the <strong> element is (the simplest):

/* define a colour for the <p>
   elements: */
p {
  color: #f90;
}

/* define a colour for the <strong>
   elements within <p> elements: */    
p strong {
  color: #000;
}

p {
  color: #f90;
}
p strong {
  color: #000;
}
<p>A paragraph with no child elements</p>

<p><strong>Local:</strong>
  <br>-Brasília/DF</p>

And a slightly more complex version, using CSS generated content:

p {
  color: #f90;
}
p[data-label]::before {
  content: attr(data-label) ': ';
  color: #000;
  display: block;
  font-weight: bold;
}
<p data-label="Local">-Brasília/DF</p>

References: