Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS selector to check that attribute does not contain both values

I have a pretty odd CSS problem I want to solve.

I'm looking for any html element which does not have display: none (in any of its valid forms) inline in a style attribute.

Some examples:

  • <foo style="display:none" />
  • <foo style="display: none" />
  • <foo style="display : none" />
  • <foo style="display : none" />
  • <foo style="bar:baz; display:none" />

I've been tinkering with the :not() negation pseudo-class but the following selector is apparently invalid:

:not([style*='display'][style*='none'])

It doesn't look like you can combine other selectors within a single not()

I know that even if it worked, this could potentially create false positives for things like <foo style="border: none; display: inline" />, but I'm somewhat OK with that.

So... is there any way to do what I want aside from hard-coding a bunch of the variations?

I really don't want to resort to this:

:not([style*='display:none']):not([style*='display :none']):not([style*='display: none']:not([style*='display : none']):not([style*='display:  none'])...

Update:

The selector suggested in the comments (:not([style*=display]):not([style*=none])) will not actually work for me

Consider the following:

  1. <p></p>
  2. <p style=""></p>
  3. <p style="border: none;"></p>
  4. <p style="border: none;"></p>
  5. <p style="display: inline;"></p>
  6. <p style="border: none; display: inline"></p>
  7. <p style="display: none;"></p>
  8. <p style="display : none;"></p>
  9. <p style="display :none;"></p>

:not([style*=display]):not([style*=none]) will only select the first 2 p's.

I want it to select the first 6 (or top 5 if thats the best I can get)!

like image 938
Zach Lysobey Avatar asked Sep 04 '14 22:09

Zach Lysobey


2 Answers

As you mentioned, you want something equivalent to :not([style*='display'][style*='none']), which is invalid in CSS, since :not() allows no combined selectors.

The laws of logic help us out here. Remember that !(a AND b) == !a OR !b, so we can write

:not([style*='display']), :not([style*='none'])

since in CSS, a, b matches elements that satisfy selector a OR selector b.

Again, as said in the question, this does not take the order of the words into consideration. The latter is impossible in CSS, since none of the CSS attribute selectors consider word order.

like image 85
user123444555621 Avatar answered Oct 20 '22 09:10

user123444555621


It would clearly be better to do this with JavaScript... but here is one possible CSS solution:

p:not([style*=display]):not([style*=none]),
p[style*=display]:not([style*=none]),
p[style*=none]:not([style*=display]),
p[style*=border][style*=none] {
    color: red;
}

Example Here

As you can see, it is a little tedious. It covers a majority of cases, including the ones you listed. The more cases you want to cover, the more selectors you would need.

like image 8
Josh Crozier Avatar answered Oct 20 '22 08:10

Josh Crozier