Closed Bug 933562 Opened 11 years ago Closed 3 years ago

support compound selectors and complex selectors within :not() negation pseudo-class

Categories

(Core :: CSS Parsing and Computation, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
84 Branch
Tracking Status
relnote-firefox --- -
firefox84 --- fixed

People

(Reporter: lucas, Assigned: emilio)

References

(Blocks 2 open bugs, )

Details

(Keywords: dev-doc-complete, parity-safari)

Attachments

(2 files)

Attached file not bug.html
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0 (Beta/Release)
Build ID: 20130910160258

Steps to reproduce:

Created a simple CSS selector using an element and a class inside a :not(). It seems to work fine if the :not() contains only a single element or class, but fails when they're combined.


Actual results:

got this in the console:
Timestamp: 2013-11-01 12:02:58
Warning: Missing closing ')' in negation pseudo-class '.'.  Ruleset ignored due to bad selector.
Source File: ***/not%20bug.html
Line: 6, Column: 9
Source Code:
   :not(p.foo) {


Expected results:

rule parsed and style applied
We don't yet support compound selectors like "p.foo" inside :not().  CSS Selectors Level 3 allows only simple selectors (like "p" or ".foo" but not both together), while Level 4 relaxes this restriction.

http://dev.w3.org/csswg/selectors3/#negation
http://dev.w3.org/csswg/selectors4/#negation
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Windows 7 → All
Priority: -- → P5
Hardware: x86_64 → All
Summary: css not parse → support compound selectors or complex selectors within :not() negation pseudo-class
Version: unspecified → Trunk
Thanks.
Sorry about the **** summary. Looks like the one I wrote reverted to the search terms I began with.
Blocks: selectors-4
Summary: support compound selectors or complex selectors within :not() negation pseudo-class → support compound selectors and complex selectors within :not() negation pseudo-class
Whiteboard: [parity-safari][parity-webkit]
Mass bug change to replace various 'parity' whiteboard flags with the new canonical keywords. (See bug 1443764 comment 13.)
Keywords: parity-safari
Whiteboard: [parity-safari][parity-webkit]
From bug 1348802:
> We should downgrade to level 3 and then reconsider after stylo ships. I have a patch.

Time to reconsider?
Flags: needinfo?(bobbyholley)
Priority: P5 → --
See Also: → 1348802
(In reply to Dão Gottwald [::dao] from comment #6)
> From bug 1348802:
> > We should downgrade to level 3 and then reconsider after stylo ships. I have a patch.
> 
> Time to reconsider?

This is not so easy fwiw, Servo's implementation had no invalidation support whatsoever. Compound selectors are easy to implement, combinators... not so.
(In reply to Emilio Cobos Álvarez (:emilio) from comment #7)
> (In reply to Dão Gottwald [::dao] from comment #6)
> > From bug 1348802:
> > > We should downgrade to level 3 and then reconsider after stylo ships. I have a patch.
> > 
> > Time to reconsider?
> 
> This is not so easy fwiw, Servo's implementation had no invalidation support
> whatsoever. Compound selectors are easy to implement, combinators... not so.

Well, selector list invalidation is going away inside `:is(…)`, `:where(…)`, `:not(…)` and other Level 4 and higher selectors that take a selector list as an argument in https://github.com/w3c/csswg-drafts/issues/3264.
(In reply to ExE Boss from comment #8)
> Well, selector list invalidation is going away inside `:is(…)`, `:where(…)`,
> `:not(…)` and other Level 4 and higher selectors that take a selector list
> as an argument in https://github.com/w3c/csswg-drafts/issues/3264.

I'm not talking about that invalidation. I'm talking about restyling, that is, making sure that we restyle as little as possible when for example a class changes in a selector like:

  .foo bar:not(.bar + baz)

Handling the .bar change is non-trivial.
I'll defer to Emilio.
Flags: needinfo?(bobbyholley)
Type: defect → enhancement

This should be pretty easy after bug 1509418.

Depends on: 1509418

This fixes the failures this bug is about and should just work with the
invalidation improvements I did for :is / :where.

It seems Chromium is adding tests for that1 so I'll wait for those
before landing and ensure they pass.

Assignee: nobody → emilio
Status: NEW → ASSIGNED
Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/fd29ba131d13
Implement complex :not(). r=jfkthame
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/26330 for changes under testing/web-platform/tests
Pushed by emilio@crisal.io:
https://hg.mozilla.org/integration/autoland/rev/4ae6c523d160
Annotate a few tests that have landed in the meantime.
Status: ASSIGNED → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 84 Branch
Upstream PR merged by moz-wptsync-bot
Blocks: 1677247

Added to release notes, updated BCD and example on MDN property page.

Release Note Request (optional, but appreciated)
[Why is this notable]: Very convenient new CSS feature
[Affects Firefox for Android]: yes
[Suggested wording]: :not CSS selector now supports selector lists and more complex selectors
[Links (documentation, blog post, etc)]: https://caniuse.com/css-not-sel-list

here's the MDN page: https://developer.mozilla.org/en-US/docs/Web/CSS/:not (compat data needs updating for FF 84)

tldr: :not(X):not(Y):not(Z) or :not(:is(X,Y,Z)) can now be :not(X, Y, Z)

relnote-firefox: --- → ?

(In reply to Tim Nguyen :ntim from comment #21)

tldr: :not(X):not(Y):not(Z) or :not(:is(X,Y,Z)) can now be :not(X, Y, Z)

:not(x):not(y) is not equivalent to :not(x, y) afaict.

If you match x but not y, then one applies but other doesn't.

(In reply to Emilio Cobos Álvarez (:emilio) from comment #22)

(In reply to Tim Nguyen :ntim from comment #21)

tldr: :not(X):not(Y):not(Z) or :not(:is(X,Y,Z)) can now be :not(X, Y, Z)

:not(x):not(y) is not equivalent to :not(x, y) afaict.

If you match x but not y, then one applies but other doesn't.

I struggle to make sense of this. From what I remember we've been using :not(foo):not(bar) and :not(:is(foo, bar)) interchangeably. https://caniuse.com/css-not-sel-list also states that:

:not(a):not(.b):not([c]) can instead be written as :not(a, .b, [c])

These are equivalent from what I can tell:

<style>
#a :not(:disabled):not(:hover),
#b :not(:is(:disabled, :hover)),
#c :not(:disabled, :hover) {
  outline: 1px solid red;
}
</style>
<p id="a">
  <input type="button" disabled>
  <input type="button">
</p>
<p id="b">
  <input type="button" disabled>
  <input type="button">
</p>
<p id="c">
  <input type="button" disabled>
  <input type="button">
</p>
Flags: needinfo?(emilio)

Err, yeah, I got that wrong, sorry.

They are in fact equivalent, because :not(a):not(b) is effectively !a && !b, and :not(a, b) or :not(:is(a, b)) is just !(a || b), which is the same, that is, will only really match when both are false.

Flags: needinfo?(emilio)
Blocks: 1679452
Blocks: 1679463

We generally don't add feature like this to the general release notes. MDN is the right place for it.

Regressions: 1685621
Regressions: 1881517
No longer regressions: 1881517
You need to log in before you can comment on or make changes to this bug.