Closed Bug 418039 (has-pseudo) Opened 16 years ago Closed 3 months ago

Implement the :has() pseudo class

Categories

(Core :: CSS Parsing and Computation, enhancement)

enhancement

Tracking

()

RESOLVED FIXED

People

(Reporter: josh, Unassigned)

References

(Depends on 3 open bugs, Blocks 4 open bugs, )

Details

(Keywords: dev-doc-needed, parity-chrome, parity-safari)

For numerous reasons, I would really like to have has-child and has-descendant selectors in CSS.  These selectors would select an element which has an immediate child matching a selector or a descendant matching a selector, respectively.

To avoid conflicting with any official CSS feature, this should most likely use CSS extension syntax, which would make the selectors -moz-has-child and -moz-has-descendant.

These selectors would allow rules such as:

/* Put a red border around forms that have a field with class="error". */
fieldset:-moz-has-child(.error) { border: 1px solid red; }

/* Show a message asking the user to mark at least one checkbox from
   the form. */
form.choices:-moz-has-descendant(*:checked) div.warning { display: none; }

/* Highlight the section containing the current anchor. */
div:-moz-has-descendant(*:target) { background-color: yellow; }

/* Put a page break before tables which have at least 20 rows, putting
   them at the top of their own page. */
table:-moz-has-child(tr:nth-of-type(20)) { page-break-before: always; }

/* Put a border between sections, treating divs as sections if they
   contain an h2 as their first child. */
div:-moz-has-child(h2:first-child) { border-bottom: 1px solid black; }

/* Picture the following as an Adblock Plus rule; it could easily
   replace many of the heuristics currently used to block the
   containing elements of ads, such as matching divs with a given
   width or style. */
div:-moz-has-child(img[href^="http://adserver.example.org"]) { display: none; }


I think these examples show some of the promise of these selectors.
These proposals look more like the :matches() and :has() proposals than the :subject proposal that was in early drafts of css3-selectors.  That said, they're all extremely inefficient to implement.  The danger of implementing them is that authors might use them, and then either authors or users will complain about how (unavoidably) slow they are.
Looking at that proposal, I like :subject much better than the approach I've suggested.  :subject avoids introducing new syntax which lacks symmetry with the existing selectors.  All but one of the examples I gave seems to work with the :subject selector:

/* Put a red border around forms that have a field with class="error". */
fieldset:subject > .error { border: 1px solid red; }

/* Highlight the section containing the current anchor. */
div:subject *:target { background-color: yellow; }

/* Put a page break before tables which have at least 20 rows, putting
   them at the top of their own page. */
table:subject tr:nth-of-type(20) { page-break-before: always; }

/* Put a border between sections, treating divs as sections if they
   contain an h2 as their first child. */
div:subject h2:first-child { border-bottom: 1px solid black; }

/* Picture the following as an Adblock Plus rule; it could easily
   replace many of the heuristics currently used to block the
   containing elements of ads, such as matching divs with a given
   width or style. */
div:subject img[href^="http://adserver.example.org"] { display: none; }


The one example that doesn't work:

/* Show a message asking the user to mark at least one checkbox from
   the form. */
form.choices:-moz-has-descendant(*:checked) div.warning { display: none; }

That one requires applying subject and then applying further CSS combinators starting from the element chosen by :subject:

(form.choices:subject *:checked) div.warning

While useful, I can definitely live without that, and it might prove inefficient as well as complex to implement.

However, the :subject selector itself does not seem fundamentally less efficient than other CSS selectors or combinators.  It does seem harder to implement, but not computationally harder.  The main difficulty seems more likely to come from the need to process child elements before rendering the parent.  However, in terms of computation, what if Gecko simply matched the CSS rule precisely as it would without :subject, and then *once it found a matching element* it went up to the :subject element and applied the style?  That seems no less efficient than existing CSS rules.
It is computationally harder.  Just matching as though :subject weren't there is far from trivial (if possible at all), for a number of reasons:
 * "div:subject p" can match many divs for a single p
 * "div:subject :link:hover" mean we need to recompute style for the entire document when somebody changes whether they're hovering over a link.

That said, by caching a bunch of things in various places and being very careful about what caches to invalidate when, it might be possible.
Er, what I meant is that any reasonably simple way of implementing it is computationally harder.  However, there might be some tricks we could use to avoid that, but they're far from trivial, if possible at all.
Actually, if we cache on each node (or maybe even on the style context -- that might be a little trickier) the list of nodes matching rules that would normally have it as a subject but instead had a :subject, it probably wouldn't be that bad, although processing the reresolution process would be tricky.  We'd need to build lists of what needed rules changed outside the tree we're reresolving style on -- and then we'd need something like ReParentStyleContext to do a bunch of rebuilding.  Except to make this efficient we'd probably want to do something like cache an mNextRuleNode on style contexts -- along with caching both old and new lists of the external rules.  Or something roughly like that.
Summary: CSS parent (has-child) and ancestor (has-descendant) selectors → CSS parent (has-child) and ancestor (has-descendant) selectors (:subject)
Caching on the style context would be tricky because of the FindChildWithRules optimization.
The other things that would be bad are:
 * potentially messy re-resolution as we matched rules on descendants (for style contexts that we'd already resolved)

 * having to do style resolution inside display:none subtrees just to match things whose :subject is outside the subtree
Blocks: selectors-4
Keywords: dev-doc-needed
The current editors draft proposes :has().
Summary: CSS parent (has-child) and ancestor (has-descendant) selectors (:subject) → Implement the :has() pseudo class
Blocks: 1169065
How much priority should this have?
It's been years and still no priority.... To be honest I really wanted to start using this on my websites....
Flags: needinfo?(mreavy)
Just so you know: If you use jQuery then you can already use it.
I think you got it wrong. This is for CSS. jQuery is a javascript library, m8...
If it was about finding such stuff with javascript, I would have already solved it quite long ago. Currently, I have a javascript hack to do the job which is not fast enough for our objectives.
(In reply to brunoais from comment #13)
> I think you got it wrong. This is for CSS. jQuery is a javascript library,
> m8...
> If it was about finding such stuff with javascript, I would have already
> solved it quite long ago. Currently, I have a javascript hack to do the job
> which is not fast enough for our objectives.

:has would only be available on the static profile (that is, querySelector), so it wouldn't help you anyway? It'd be way to slow to allow its use in stylesheets.
If I understood right, the ":has()" has the same meaning as the proposed "$", "^" or "!" selector.
Why do you believe it is a slow selector? The node being selected will be in the nodes found stack when running the processing.

If I have:
<div class="a">
	<div class="b1">
		<div class="c1">
			<div class="d1">Must not find b container of me</div>
		</div>
	</div>
	<div class="b2">
		<div class="c2">
			<div class="d2 findMe">Find b countainer of me</div>
		</div>
	</div>
</div>

Example 1:

a *:has(.findMe)
->
Finds all that match ".findMe" (indexed class search)
Go up the tree.... Pass through (in order):
- .c2 (push .c2 node as possible apply style)
- .b2 (push .b2 node as possible apply style)
- a (Found a)

Add to the cascade table: apply style to c2 and b2

Example 2:

:has(.findMe)
->
Finds all that match ".findMe" (indexed class search)
Go up the tree.... Pass through (in order):
- .c2 (push .c2 node as possible apply style)

Add to the cascade table: apply style to c2

Example 2:

a:has(.d1)
->
Finds all that match ".d1" (indexed class search)
Go up the tree.... Pass through (in order):
- .c1
abort


I know these are cases where only one node is found by rightmost selector but the basic idea is the exact same
Regardless, :emilio do explain why is :has() is so slow so not to implement on a stylesheet? The above comments approach towards a possible solution before stylo. Now, with stylo, the performance results can be quite different
Flags: needinfo?(emilio)
Cherry-picking most trivial cases to prove the point? Nice try. 

First of all you have no way to decide if you should go up or down the tree to be "faster" and either of will be slow in most cases really. Let's take a:has(.d1). Imagine there are 10000 .d1 nodes and one a. And now imagine there are 1 .d1 and 10000 a. And additionally there might be really deep tree. And then you can have div:has(a) and now what you do?

As for :has selector, currently you can use XPath (better and faster than implementing :has by hand in JS) where you can make query explicitly specifying if you want to go up or down the tree, and have other constrains that reduce search space.

Bottom line is if you really need the :has selector you might want to change your design.
You're making assumptions about how a browser does style computation that are not true in any browser.

The way browser compute the style for an element is checking whether the same element matches all the selectors in the site, not the other way around (as you're suggesting, given a selector, finding all the elements that match, and stashing the result in some kind of global table).

That is, selector-matching works looking up and to the left of the tree following combinators. To implement :has you need to potentially look at all the descendants of an element, which is something that no other selector requires you to do.

Additionally, supporting :has in stylesheets would have another deep implication, which is that a change in an element could now affect the style of its ancestors, which is just something that doesn't happen with other selectors, and that engines rely on to handle dynamic changes efficiently.
Flags: needinfo?(emilio)
> If I understood right, the ":has()" has the same meaning as the proposed "$", "^" or "!" selector.

I haven't seen those, and I don't know the right search terms to find them. Would you mind pointing to a reference for them?
:kasper93 :
Oh, you mean:
Situation 1:
A web page with 10000 .d1 nodes and a single a node. In that case, the difficulty of:
"a:has(.d1)" is the same as "a .d1". "a .d1" already exists as valid so I don't see anything wrong there.

Situation 2:
A web page with a single .d1 node and 1000 a nodes. In that case, the difficulty of:
"a:has(.d1)" is, indeed, more complex than "a .d1". That is because the algorithm always has to run until the ":root" tag to find all matches.
If the node with class "d1" is not inside any of the <a> tags, then the computation required is the same as there was no ":has()". Otherwise, it relies on how deep the single tag of class "d1" is. In a realistic situation, though, a tag is not placed 1000 tags deep. In the most complex websites, the closest ":root" or ":scope" tag is no more than 50 tags deep. In such realistic situation, only, at most, 47 tags would be the a tags referred there. The rest to the 1000 a tags would be ignored while processing that selector because they would not be in the upwards search graph.

As for: "div:has(a)"... What's the issue with that one? 
It is true it is more efficient to have "div:has(> a)" but it is still the same kind of thing. I don't get the problem with that

:emilio
> The way browser compute the style for an element is checking whether the same element matches all the selectors in the site, not the other way around (as you're suggesting, given a selector, finding all the elements that match, and stashing the result in some kind of global table).
OK

> That is, selector-matching works looking up and to the left of the tree following combinators. To implement :has you need to potentially look at all the descendants of an element, which is something that no other selector requires you to do.
True from a conceptual standpoint but it doesn't have to be implemented that way.

> Additionally, supporting :has in stylesheets would have another deep implication, which is that a change in an element could now affect the style of its ancestors, which is just something that doesn't happen with other selectors, and that engines rely on to handle dynamic changes efficiently.
OK. That is a good point.

> I haven't seen those, and I don't know the right search terms to find them. Would you mind pointing to a reference for them?
It's not easy to find... Still... I found a commit of when the idea of w3c at the time was to use "!"
https://github.com/w3c/csswg-drafts/blob/3e071f642fa737adce2a7c8529606049f29fdaff/selectors/Overview.html#L1245

The "$" was very very short lived... after 20 minutes looking for it in the drafts, I couldn't find it.
The "^" I don't remember but I did find it being mentioned in an article from that time.
See: https://hugogiraudel.com/2014/02/13/parent-selector/

There are mentions about "!" in one of the comments of: https://css-tricks.com/parent-selectors-in-css/ back when it was very young.

I think that's about it of what I can find. There were not many news at the time too.
Flags: needinfo?(mreavy)
(In reply to David Baron :dbaron: 🏴󠁵󠁳󠁣󠁡󠁿 ⌚UTC-7 from comment #1)
> ...
> ...
> ... extremely inefficient to implement.  ...
> ... will complain about how (unavoidably) slow they are.

Can't the algorthim just break up at a certain point, when the nesting/recursion (or whatever makes it inefficient) gets too deep/high and leave a warning in the console?
You forgot to "?needinfo" him
Flags: needinfo?(dbaron)
I actually thought this would be a rule that can be almost directly solved...
For "a:has(b.show)", for example, it would just be the same work as matching "a b.show" except it is "a" tag that gets the rules applied instead of "b" tag.....
(In reply to altugtekin85 from comment #20)
> Can't the algorthim just break up at a certain point, when the
> nesting/recursion (or whatever makes it inefficient) gets too deep/high and
> leave a warning in the console?

A warning in the console and a broken web page?  I don't think such an approach could work unless the limits were specified, but it's not clear what it is you're proposing to limit, or how that would interfere with the use cases for the feature.  (I could try to work that out... but it seems like a decent amount of work that isn't an appropriate use of "needinfo?".)
Flags: needinfo?(dbaron)
In your first comment you state that:
(In reply to David Baron :dbaron: 🏴󠁵󠁳󠁣󠁡󠁿 ⌚UTC-7 from comment #1)
> ... they're all extremely inefficient to implement. The danger of implementing
> them is that authors might use them, and then either authors or users will
> complain about how (unavoidably) slow they are.

Given that statement I concluded, that when the browser is evaluating the CSS containing the "has()" it somehow enters an inefficient loop, which has an exponential (or n^99) runtime. And my thought was that, if I knew the source code better and had the time to edit it, I would simply count the number of iterations the browser spends in the loop and eventually at a fixed value break out of the loop, so that nobody complains about bad performance, but on the other hand leaves a warning, thsat the developer must change his/her CSS in order to make it work again.

(In reply to David Baron :dbaron: 🏴󠁵󠁳󠁣󠁡󠁿 ⌚UTC-7 from comment #23)
> (In reply to altugtekin85 from comment #20)
> > Can't the algorthim just break up at a certain point, when the
> > nesting/recursion (or whatever makes it inefficient) gets too deep/high and
> > leave a warning in the console?
> 
> ... but it's not clear what it is you're proposing to limit ...

Was the above explanation elaborate enough?
A reference: This feature is implemented first(?) in Prince 12 https://www.princexml.com/. See the documentation here: https://www.princexml.com/doc-refs/ [search ":has("]. I use it to generate PDF from XML or HTML.

I would like to use this feature in Firefox to preview a _static_ (CSS formatted) XML document. Is this case part of "snapshot profile" described in CSS 4 Selector Specification here: https://drafts.csswg.org/selectors/#snapshot-profile?

Please implement it as "exclamation" version .
The div p!+ul>li is more readable than div+p:has(+ul>li). Excalamtion mark to point element to be style applied.

Safari 15 has experimental for support

Safari Technology Preview Release Notes - Release 137

Enabled support for :has() pseudo-class by default
https://developer.apple.com/safari/technology-preview/release-notes/

Blocks: 1748399
Blocks: 1747667

It looks like the Chromium team is also actively working on an implementation under https://crbug.com/669058.

Sebastian

(In reply to Mozira from comment #27)

Please implement it as "exclamation" version .
The div p!+ul>li is more readable than div+p:has(+ul>li). Excalamtion mark to point element to be style applied.

Ternary-style operators are not more readable; I think most authors would consider it far less readable than an explicit descriptive word. CSS does not use ternary-style operators for anything else, to my knowledge, so it would be a change in form to do so here, and would cause needless confusion, considering not only the CSS specification but also other vendors (Safari and Chrome) use ":has()" already.

(In reply to Tyler from comment #32)

(In reply to Mozira from comment #27)

Please implement it as "exclamation" version .
The div p!+ul>li is more readable than div+p:has(+ul>li). Excalamtion mark to point element to be style applied.

Ternary-style operators are not more readable; I think most authors would consider it far less readable than an explicit descriptive word. CSS does not use ternary-style operators for anything else, to my knowledge, so it would be a change in form to do so here, and would cause needless confusion, considering not only the CSS specification but also other vendors (Safari and Chrome) use ":has()" already.

It's not a request for a ternary operator. I don't understand why you understood like that but that's not the important part.
The request is to use the ! character as the marker of which element is intended to be obtained, not as a ternary operator. It can be some other character. Can be an @ character even. It's just that that is shorter than a function-like format.

As for me, I don't really mind which way it's actually done as long as the feature is there and it's as usable as eachever.

(In reply to brunoais from comment #33)

(In reply to Tyler from comment #32)

Please implement it as "exclamation" version .
The div p!+ul>li is more readable than div+p:has(+ul>li). Excalamtion mark to point element to be style applied.

It's not a request for a ternary operator. I don't understand why you understood like that but that's not the important part.
The request is to use the ! character as the marker of which element is intended to be obtained, not as a ternary operator. It can be some other character. Can be an @ character even. It's just that that is shorter than a function-like format.

As for me, I don't really mind which way it's actually done as long as the feature is there and it's as usable as eachever.

I am not in support of a shortened syntax. How would you you get further selection outside the has? For example, div+p:has(+ul>li)+p from div+p!+ul>li+p? The interpreter would easily see this as being div+p:has(+ul>li+p) instead which may not be what you were looking to do.

Please note that this is not the place to discuss the syntax of this feature. The right place would be the GitHub repository of the CSS Working Group.

Having said that, I'm afraid that this ship has already sailed. There were many discussions regarding ! vs. :has() and other ways to express a parent selector and the Working Group decided on :has() in the end. Furthermore, as Tyler already mentioned, WebKit already shipped this and people are working on an implementation for Chromium.
So, it's very unlikely that the syntax will be reconsidered at this point.

Sebastian

This feature needs to be implemented experimentally in Firefox (by making it enableable via about:config).

This will allow:

  • to experiment with this feature
  • to allow performance testing
  • accelerate the chances of adoption

Patches welcome, fwiw. I'm not likely to get to this super-soon (but it's in the roadmap)

Emilio, can we please see your roadmap? :)

Currently that document (which is specific for the Layout / APZ teams) is Mozilla-internal. It doesn't have any secrets, so I can try to ask to make it public. That said, it's subject to change so not sure you could draw a lot of conclusions...

The layout team standup notes are public tho, and probably a better view of what the team is up-to, if that's what interests you :-)

Chromium has published their "intent to ship": https://groups.google.com/a/chromium.org/g/blink-dev/c/bRsbl3wLuyk/m/mt3iSKNHBQAJ?pli=1

Expected in Chrome 105. It would be great to get Firefox to work on this for cross-browser compatibility

Blocks: 1770370
Blocks: 1771020
Depends on: 1771692
Depends on: 1774588

The Chromium people enabled their implementation by default a few days ago.

Sebastian

See Also: → 1775267

Note, there was a CSSWG resolution in last week's working group meeting:

RESOLVED: Disallow all current pseudo-elements inside of :has(), allow future pseudo-elements to define that they are valid if useful/possible.
https://github.com/w3c/csswg-drafts/issues/7463#issuecomment-1196971909

See the examples from the first comment there:

Selectors like ol:has(li::marker) and section:has(p::first-line) are problematic and we should make all pseudo-elements invalid inside :has().

If our current implementation (e.g. via bug 1771896) is already far enough along that we accept such selectors and would need to land another patch to add restrictions to reject them, then it might be worth filing a bug on that; otherwise/alternately we can just consider this as being part of the main/remaining portion of work under this main bug here.

The following works in Edge but not in Firefox with the flag enabled:

<html>
    <meta name="viewport" content="width=device-width">
    <style>label:has(input[type="hidden"]) {
        display: none;
    }
    </style>

    <label>
        a
        <input type="hidden" name="a" value="a">
    </label>
    <label>
        b
        <input type="text" name="b" value="b">
    </label>
    </form>
</html>

(In reply to cyril.walle from comment #45)

The following works in Edge but not in Firefox with the flag enabled:

<html>
    <meta name="viewport" content="width=device-width">
    <style>label:has(input[type="hidden"]) {
        display: none;
    }
    </style>

    <label>
        a
        <input type="hidden" name="a" value="a">
    </label>
    <label>
        b
        <input type="text" name="b" value="b">
    </label>
    </form>
</html>

Even after fixing the HTML it doesn't work as expected:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
    <style>label:has(input[type="hidden"]) {
        display: none;
    }
    </style>
</head>
<body>
    <label>
        a
        <input type="hidden" name="a" value="a">
    </label>
    <label>
        b
        <input type="text" name="b" value="b">
    </label>
</body>
</html>

Like this, both labels are not displayed.
If you swap the labels, both labels are displayed

The problem seem to be that only the first label is being evaluated (or the only one whose evaluation counts) and then applying the same value to all other labels. This can be a cache issue...

It's expected that there are bugs, :has() implementation is experimental, that's why it's not enabled anywhere by default.

.matches / .querySelector are expected to behave correctly. What you're seeing is an interaction with the style sharing cache where we try to detect when we can just share the style of the elements. It's not accounting for :has, so it wrongly shares the style of the first label with the second.

Depends on: 1792501
Severity: normal → S3

The implementation not the spec is experimental.

It's expected that there are bugs, :has() implementation is experimental, that's why it's not enabled anywhere by default.

And to iterate on that, the implementation in Firefox (Gecko) is experimental. And "not enabled anywhere by default" means not enabled in any Firefox version by default yet.

Sebastian

Child/sibling combinators inside :has() are ignored.
The following works in Chroimum, but not in Firefox with the flag enabled.

<style>
 div:has(> span){ font-size: 150%; }
 div:has(+ div){ color: red; }
 div:has(~ div){ border: thin solid black; }
</style>

<div>
  <span>a</span>
</div>

<div>
  b
</div>

(In reply to teterumu from comment #52)

Child/sibling combinators inside :has() are ignored.

They are not implemented yet. See bug 1774588.

Sebastian

Pseudo-classes do not seem to work inside :has().
I tried :not, :checked, :valid/:invalid.

Here is example with :not

<style>
div:has(h1) {
  background: red;
}

div:has(:not(h1)) {
  background: green;
}
</style>

<div>
  <h1>h1</h1>
</div>

<div>
  <h2>h2</h2>
</div>

All of them work in Brave browser (Chromium based).

As mentioned in the previous comments, :has() isn't fully implemented in Gecko yet, which is why it's still behind the layout.css.has-selector.enabled preference, which is disabled by default.
You may want to have a look at the bugs linked to in the "Depends on" and "Blocks" list above, especially bug 1771692 and bug 1748399, which relate to pseudo-classes within :has().

Sebastian

Duplicate of this bug: 1808287

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

Currently that document (which is specific for the Layout / APZ teams) is Mozilla-internal. It doesn't have any secrets, so I can try to ask to make it public. That said, it's subject to change so not sure you could draw a lot of conclusions...

The layout team standup notes are public tho, and probably a better view of what the team is up-to, if that's what interests you :-)

Checking the links on the [mozilla wiki](https://wiki.mozilla.org/Platform/Layout the notes linked above seem to be still the most up-to-date document, even though their last entry is from six months ago. Can you tell if a push for getting :has() ready to be shipped is anywhere on a current roadmap? I had a look at the tickets mentioned by Sebastian above, but they haven't been active for 7/12 months respectively.

(In reply to Albert Scheiner [:alberts] from comment #59)

their last entry is from six months ago.

This link goes up to last week:

https://docs.google.com/document/d/1BbKGHgmDjD87f6Dt4mMXrZysch5END7AoCIY1cwGSdY/edit

Blocks: 1771692
No longer depends on: 1771692

I recieved a question via Support, any update on when the :has() CSS selector will be supported?, is there any ETA of this?

Thanks

Flags: needinfo?(emilio)

We plan to work on this in the first half of this year.

Flags: needinfo?(emilio)
Depends on: 1813321
Blocks: interop-2023
Alias: has-pseudo
Duplicate of this bug: 1816116
No longer depends on: 1813321
Depends on: 1820835

Is there any update on this? @emilio? A timeline?

I have a system I'm hoping to release in the fall that would be best done using :has, but now, even with the config flag set on v.111.01, it's simply not working.

Flags: needinfo?(emilio)

There's work going in progress on this. It's not expected that it doesn't work with the flag off (specially on release instead of nightly where the latest changes land), that's why it's off by default.

Flags: needinfo?(emilio)

Hello. I don't want to add unnecessary bug noise, but I was trying out :has() in a low-critical area to tweak handling of row highlighting. I ran into a couple of bugs that I put in a testcase here:
https://m8y.org/tmp/testcase500.xhtml
Testcase demoing an issue where Firefox Nightly 2023-03-24 with :has() enabled leaves hover highlighting active (move down the rows in column E or F), or does not apply hover highlighting (move up from the bottom into the Y cells).

I was wondering if this was known. I didn't spot it in the linked bugs. Chrome seems to evaluate my CSS as I expected.

Depends on: 1827164
Blocks: 1825176
Depends on: 1822177
Depends on: 1775267
See Also: 1775267
Duplicate of this bug: 1834393
Depends on: 1836563
Duplicate of this bug: 1838773

This tweet gained a good deal of traction over the past couple days. @Emilio do you have any update? We're nearing the end of H1 already by now.

Flags: needinfo?(emilio)

There's a fair amount of ongoing work in dependent bugs, please follow those for progress.

Flags: needinfo?(emilio)
Depends on: 1835037
Depends on: 1839069

Just an FYI that (currently widely used) Tailwind CSS will have :has() classes in its upcoming release:
https://twitter.com/adamwathan/status/1663582608528224257
https://github.com/tailwindlabs/tailwindcss/pull/11318

Depends on: 1843103
Depends on: 1845291
Depends on: 1845095
Depends on: 1845503

(In reply to Kenneth Hoff from comment #76)

Where can I go to get news on this feature? Can we expect it before the end of the year?

This bug and the ones blocking it are probably the best place to follow the implementation of :has().
As it is actively being worked on and it is part of the Interop 2023 initiative, I assume it will be released this year. Having said that, I'm also just a follower and not an implementer.

Sebastian

Depends on: 1847072
Blocks: 1847866
Depends on: 1852965
Blocks: 1853258
Depends on: 1853701
Blocks: 1839069
No longer depends on: 1839069
Depends on: 1855690
No longer depends on: 1855753
Depends on: 1855994

I just tested on Firefox Nightly 120, it looks like it's finally there! Here's the Interop 2023 page referencing the feature: https://wpt.fyi/results/css/selectors/dir-pseudo-in-has.html?label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=subtest&q=label%3Ainterop-2023-pseudos

Yup! This was recently enabled by default on Nightly (only Nightly for now), in bug 1853701.

No longer blocks: 1853258
Depends on: 1853258
Depends on: 1858743
Depends on: 1860136
Depends on: 1860373
Depends on: 1861704
Depends on: 1846755

(In reply to Daniel Holbert [:dholbert] from comment #79)

Yup! This was recently enabled by default on Nightly (only Nightly for now), in bug 1853701.

Any idea about when this could land on stable? Funny to see Nightly is the first browser at 100% interop compat on the :has() subject though!

Any idea about when this could land on stable?

Firefox 121 (see bug 1858743).

Depends on: 1867893

This example (last example on page) using a combination of :not and :has to create a dotted border still doesn't seems to work in 121 beta og 122 nightly. Is this a bug or am I missing something?

Christian Aarfing: the website you pointed to doesn;t have the correct CSS applied to it. Their linked Pen does have the CSS code and it seems to work correctly: https://codepen.io/matuzo/pen/poKxKEN

(In reply to Jamie Katz from comment #83)

Christian Aarfing: the website you pointed to doesn;t have the correct CSS applied to it. Their linked Pen does have the CSS code and it seems to work correctly: https://codepen.io/matuzo/pen/poKxKEN

Thank you. You're probably right. It threw me that it worked in Safari and Chrome :)

Actually, I think I'm wrong, sorry! The page does have this CSS:

.democard3.card:not(:has(img))
{
  border-style: dotted;
}

But it doesn't get applied on FF (Nightly 2023-12-13) or show up in devtools. In devtools if I add/remove one of the classes from the .democard3 (the one without the img), it does apply the :has CSS and show up.

Funnily, there doesn't seem to be the same problem on the Pen page https://codepen.io/matuzo/pen/poKxKEN

.right:not(:has(img))
{
  border-style: dotted;
}
Depends on: 1869771

FF121.0.0 - In Inspector's Search HTML field:

element:has(element) doesn't work. E.g. body:has(main). The suggestion shows body:h when I close the parenthesis.

It works fine with attribute attribute, class and ID selectors. If work fine with a child or subsequent sibling combinator. No suggestions though.

It doesn't work with the next-child combinator for element names either.

header:has(+main) doesn't work. (The suggestion shows header:has(+main)r)

Interestingly enough, neither does header+main. Even though it does get suggested when typing.

Thanks, filed that as bug 1871881, but for the next time, please do not use comments to report bugs or enhancements, use the relevant form. Otherwise, it relies on me or someone else noticing the comment, then remembering to file it, and it makes harder to follow-up with the original reporter etc as needed.

I'm going to close this bug, since this is implemented, and file a follow-up bug for tracking :has() - related bugs.

Status: NEW → RESOLVED
Closed: 3 months ago
Resolution: --- → FIXED
See Also: → 1871881
You need to log in before you can comment on or make changes to this bug.