[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-conditional-5][css-nesting-1] Feature detection for nesting #8399

Open
SebastianZ opened this issue Feb 4, 2023 · 43 comments
Open

[css-conditional-5][css-nesting-1] Feature detection for nesting #8399

SebastianZ opened this issue Feb 4, 2023 · 43 comments
Labels
css-conditional-5 Current Work css-nesting-1 Current Work

Comments

@SebastianZ
Copy link
Contributor

We need to provide a smooth way to transition to nesting, so authors can detect whether nesting is supported by the user agent. So they can provide fallback solutions for UAs that don't support it.

There where already some prior discussions related to this topic, though no explicit issue or resolution regarding this, as far as I can tell.

The major discussion related to this is #8349, but its focus is rather on error recovery than feature detection. Another slightly related one is #2463, though it rather features detection of at-rules and their descriptors.

So I opened this issue to explicitly discuss how nesting support can be made detectable. I believe this is a must for any implementation for shipping nesting capabilities to reach a high level of adoption and avoid page breakages.

Sebastian

@SebastianZ SebastianZ added css-nesting-1 Current Work css-conditional-5 Current Work labels Feb 4, 2023
@SebastianZ
Copy link
Contributor Author

Maybe the simplest solution would be to reuse the selector() function for that.

So this could detect whether nesting style rules is supported:

@supports selector(& .foo) {
  …
}

Though that only covers style rules. Support for nesting other rules like media queries might require a different approach. One solution would be to support testing of complete rules, as I suggested earlier. An example of that could look like this:

@supports (.foo { @media (width >= 500px) { } }) {
  …
}

Another, more flexible but also more complex approach would be script based queries, which I also suggested earlier.

Sebastian

@Loirooriol
Copy link
Contributor

I highly doubt authors will use something like

@supports selector(& .foo) {
  .wrapper {
    color: magenta;
    & .foo { color: cyan; }
  }
}
@supports not selector(& .foo) {
  .wrapper { color: magenta; } 
  .wrapper .foo { color: cyan }
}

They will just use the good ol

.wrapper { color: magenta; } 
.wrapper .foo { color: cyan }

The only reasonable fallback strategy seems using JS to read the raw contents of the <style>, parse it manually, and if there are nested rules, desugar them. But detecting support for nesting in JS is already possible:

function supportsCSSNesting() {
  try {
    document.querySelector("&");
    return true;
  } catch (e) {
    return false;
  }
}

Support for nesting other rules like media queries is also posssible:

var style = document.createElement("style");
style.textContent = ".foo { @media (width >= 500px) { } }";
document.head.append(style);
var {sheet} = style;
style.remove();
return sheet.cssRules[0]?.cssRules?.length === 1;

We may want to add nicer ways, but I don't think it's a must.

@plinss
Copy link
Member
plinss commented Feb 5, 2023

I agree that authors will likely not write single stylesheets with both nested and un-nested versions of selectors. They'll either, as you say, write the stylesheet without nesting until they no longer care about older browsers, or use a preprocessor and let it emit the un-nested version.

However, what's reasonable, and should be encouraged, would be:

@import "nested-and-small.css" supports(selector(&));
@import "not-nested-and-large.css" not supports(selector(&));

(or ideally do the equivalent in <link> tags)

This way the author can use a preprocessor to generate the larger, un-nested stylesheet, but the user of a newer browser doesn't have to pay the download cost.

While nesting should be detectable via script, we need to be able to feature detect it without script (or UA sniffing) as well.

@SebastianZ
Copy link
Contributor Author

@plinss I totally agree with what you say and also thought of the usage in @import or the HTML variant for <link> elements. I guess I should have mentioned that.

@Loirooriol Relying on JS to solve this is also one of my ideas from above, though ideally JS shouldn't be a requirement for feature detection.

If testing for selector(&) is already valid, then we at least have detection support for nesting style rules.

Though being able to test for other nesting features is still important. So there's no gap between implementations and feature detectability.

Sebastian

@romainmenke
Copy link
Member
@import "nested-and-small.css" supports(selector(&));
@import "not-nested-and-large.css" not supports(selector(&));

No browser has implemented this (yet?)

https://wpt.fyi/results/css/css-cascade/import-conditions.html?label=master&label=experimental&aligned&view=subtest&q=import

@plinss
Copy link
Member
plinss commented Feb 5, 2023

No browser has implemented this (yet?)

Sure, but no browser has really implemented nesting yet either (STP and Chrome experiments not withstanding). The WG hasn't resolved on the actual mechanism to feature detect nesting yet either, the above was a (reasonable) placeholder. Given there are still open questions on the final syntax of nesting it doesn't make sense to finalize the feature detection yet.

I expect that the WG will finalize how to feature detect nesting when we finalize nesting itself, and any browser implementing nesting will implement the feature detection at the same time (it should be part of a compliant implementation).

@Loirooriol
Copy link
Contributor

@plinss In case you are not aware of it, Blink plans to ship the "experiment" in version 112. https://groups.google.com/a/chromium.org/g/blink-dev/c/eFCrkiLynfU/m/JLsh3zQuAAAJ

@romainmenke
Copy link
Member
romainmenke commented Feb 5, 2023

However, what's reasonable, and should be encouraged, would be:

This way the author can use a preprocessor to generate the larger, un-nested stylesheet, but the user of a newer browser doesn't have to pay the download cost.

This is a tangent and I don't want to derail this thread but @imports ".." not supports(selector(&)) doesn't help browsers without nesting support. Even if supports queries for @import ship simultaneously with nesting. Any @imports with a supports condition will be downloaded but never applied.

In theory it is the best method, but because it never shipped it isn't practically useful.

html sample to illustrate the issue
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>

	<style>
		/* Red */
		@import url(data:text/css;base64,Ym9keSB7IGNvbG9yOiByZWQ7IH0=);
		/* Cyan */
		@import url(data:text/css;base64,Ym9keSB7IGNvbG9yOiBjeWFuOyB9) supports(selector(&));
		/* Purple */
		@import url(data:text/css;base64,Ym9keSB7IGNvbG9yOiBwdXJwbGU7IH0=) not supports(selector(&));
	</style>
</head>
<body>
	Always red, never purple.
</body>
</html>

@plinss
Copy link
Member
plinss commented Feb 5, 2023

@plinss In case you are not aware of it, Blink plans to ship the "experiment" in version 112.

I'm aware, unfortunately just another example of Google (potentially) being Google and deciding that they know best without allowing the standards process to come to a determination of a mutually agreed best path forward. Then leveraging their market dominance to try to establish a de-facto standard. (And Apple isn't much better in their messaging around STP).

@cwilso
Copy link
Contributor
cwilso commented Feb 6, 2023

@plinss I would like to ask you to revisit this comment. We are here, participating in the standards process.

The web standards process is not now, nor has it ever been, a gate that controls features that are shipped in implementations. At the same time, as a large engine implementer, we have a responsibility to participate in good faith to build consensus on features; I believe we are doing that here. If you disagree, as per our policy (https://github.com/cwilso/standards-of-behavior), I'm happy to discuss in more depth.

@plinss
Copy link
Member
plinss commented Feb 6, 2023

@cwilso I edited my comment to remove the phrase that you found offensive. However, while I agree that Google is here, and is participating, I fail to see how shipping a feature in a form that is still under contention and discussion can be characterized as "participating in good faith". You are of course free to ship whatever you want, but you don't get to characterize paving your own path as a "standards process". Your Blink dev thread makes it clear that your shipping decision process isn't waiting for this issue to be resolved by the WG, let alone an FO.

@SebastianZ
Copy link
Contributor Author

I guess what we can agree on is that browser vendors are eager to release these nesting capabilities.
So they should also be interested in feature detectability, otherwise the adoption of this big new feature will suffer.

Sebastian

@SebastianZ
Copy link
Contributor Author

@romainmenke Very good point! So it seems that we need a different approach so that UAs with nesting support can block loading stylesheets and rules without nesting to avoid loading them twice in that case.

Sebastian

@bramus
Copy link
Contributor
bramus commented Feb 6, 2023

I’ve tested several approaches in the past:

The caveat with approach 2 is that it assumes a browser does not ship & as a selector without shipping nesting. IIRC @tabatkins mentioned somewhere (can’t seem to find back where) that & should not ship separately, so it’s safe to rely on it.

In practice, though, I don’t think authors will test nesting, as they’ll simply see the nested styles not get applied in that case:

  • Build a base style layer that doesn’t use nesting
  • Layer nested styles on top

@romainmenke
Copy link
Member
romainmenke commented Feb 6, 2023

For @supports selector(&) {} to be useful it is also critical that browsers ship support for the nesting selector at the root at the same time as actual nesting : #5745 (comment)

I've created a pull request with a basic WPT test : web-platform-tests/wpt#38373

Currently Chrome and Safari TP do not support & at the root.
If they were to ship today there would be no way to detect support for & at the root in the future.


Edit : there was already a test added recently : https://wpt.fyi/results/css/css-nesting/top-level-is-scope.html?label=master&label=experimental&aligned&view=subtest&q=nesting

@yisibl
Copy link
Contributor
yisibl commented Feb 7, 2023

@Loirooriol

Chrome(e.g. 109) returns null for document.querySelector("&") in browsers that don't support CSS nesting.

So, the detection functions need a little adjustment:

function supportsCSSNesting() {
  try {
    const s = document.querySelector("&");
    if (!s) return false; // For Chrome 109/110
    return true;
  } catch (e) {
    return false;
  }
}

Unfortunately, @supports(selector(&)) and CSS.supports('selector(&)') always returns true.
image

@sesse
Copy link
Contributor
sesse commented Feb 7, 2023

Edit : there was already a test added recently : https://wpt.fyi/results/css/css-nesting/top-level-is-scope.html?label=master&label=experimental&aligned&view=subtest&q=nesting

Even before this, I believe @supports selector(&) should have worked? The selector was defined to exist and parse just fine, just not to match anything at the root. (Now it's defined to something else, of course, but that shouldn't affect @supports.)

@romainmenke
Copy link
Member

Even before this, I believe @supports selector(&) should have worked?

It does indeed work, but the question here is if @supports selector(&) can be used as proxy for testing actual nesting support.

This approach is only viable if browsers ship nesting and "& at the root" at the same time because there is no way to differentiate between them.

@bramus
Copy link
Contributor
bramus commented Feb 7, 2023

It does indeed work, but the question here is if @supports selector(&) can be used as proxy for testing actual nesting support.

See comment above:

IIRC @tabatkins mentioned somewhere (can’t seem to find back where) that & should not ship separately, so it’s safe to rely on it.

It is the obvious/logical thing to do, but maybe it can also be enforced from within the spec?

@Loirooriol
Copy link
Contributor

I believe @supports selector(&) should have worked?

& is part of nesting, so the check should have been false with CSSNesting disabled.

It is the obvious/logical thing to do, but maybe it can also be enforced from within the spec?

Seems too late, Blink shipped & in https://chromiumdash.appspot.com/commits?commit=336be2dad52bf3454d6063bf36ea4e49a3a74aa7

@tabatkins
Copy link
Member

Yeah, I assumed we wouldn't ship the nesting selector separate from the nesting feature, as it was useless on its own and provided a nice benefit to feature detection. Ah well.

@sesse
Copy link
Contributor
sesse commented Feb 7, 2023

Blink shipped & together with nesting support. The commit you're linking to (which did indeed add nesting and & at the same time, but the version that was current at the time) was all behind an experimental flag; it would not do anything in a normal, stable browser.

@Loirooriol
Copy link
Contributor

I bisected without experimental flags and I got that commit. And effectively with the stable 109.0.5414.119 snap I can see that & is considered a valid selector even if nested rules are disabled.

@sesse
Copy link
Contributor
sesse commented Feb 7, 2023

That definitely wasn't the intention of the code, but OK, it's impossible to back and change now.

@foolip
Copy link
Member
foolip commented Feb 8, 2023

That was fixed in https://bugs.chromium.org/p/chromium/issues/detail?id=1414012 and backport requested to Chrome 111. (Thanks @sesse!)

@romainmenke
Copy link
Member

That was fixed in https://bugs.chromium.org/p/chromium/issues/detail?id=1414012 and backport requested to Chrome 111. (Thanks @sesse!)

But impossible to backport to 109 and 110 right?
So @supports selector (&) {} is no longer usable as a reliable detection?

@tabatkins
Copy link
Member

Correct, we can't fix existing versions in the wild. (Or rather, we reserve that sort of thing for OMG THE WORLD IS ON FIRE security issues.)

But Chrome versions decay in usage quickly.

@bramus
Copy link
Contributor
bramus commented Feb 13, 2023

So @supports selector (&) {} is no longer usable as a reliable detection?

(Cross-posting from Chromium’s I2S)

Authors can work around Chrome 109+110 incorrectly reporting & support by also testing for a feature that ships in any release after Chrome 110. A good candidate would be cos(), which ships in Chrome 111:

@supports selector(&) and (scale: cos(90deg)) {
  …
}

This check excludes Chrome 109+110, but includes Chrome 111 with the feature flag on.

More importantly this extended check won’t exclude Safari or Firefox, as they too support cos() – from, respectively, versions 15.4 and 108 onwards according to caniuse.com.

@yisibl
Copy link
Contributor
yisibl commented Feb 13, 2023

To be honest, feature detection here is less likely to affect users migrating to native nesting, instead, I think the more fatal problem is the desugaring to :is().

@romainmenke
Copy link
Member

To be honest, feature detection here is less likely to affect users migrating to native nesting, instead, I think the more fatal problem is the desugaring to :is().

This was revisited here : #8310
But it isn't related to and doesn't affect feature detection for nesting.

@LeaVerou
Copy link
Member

I agree that authors will likely not write single stylesheets with both nested and un-nested versions of selectors. They'll either, as you say, write the stylesheet without nesting until they no longer care about older browsers, or use a preprocessor and let it emit the un-nested version.

However, what's reasonable, and should be encouraged, would be:

@import "nested-and-small.css" supports(selector(&));
@import "not-nested-and-large.css" not supports(selector(&));

(or ideally do the equivalent in tags)

This way the author can use a preprocessor to generate the larger, un-nested stylesheet, but the user of a newer browser doesn't have to pay the download cost.

While nesting should be detectable via script, we need to be able to feature detect it without script (or UA sniffing) as well.

I suspect once Nesting has critical mass, what will be more common would be this pattern:

HTML:

<link rel=stylesheet href="nested.css">

nested.css:

@import "compiled-to-nonnested.css" not supports(selector(&));

/* nested CSS */

@romainmenke
Copy link
Member
romainmenke commented Feb 13, 2023

@import "compiled-to-nonnested.css" not supports(selector(&));

This doesn't work, it was never implemented.
So there is no advantage to it.

see : #8399 (comment)

@romainmenke
Copy link
Member

There is also no way to detect support for the even more relaxed syntax where selectors can start with an identifier.

In Chrome 113 :

CSS.supports('selector(& bar)')
// true
CSS.supports('selector(bar &)')
// true

Safari TP doesn't seem to work at all :

CSS.supports('selector(&)')
// false
CSS.supports('selector(& bar)')
// false
CSS.supports('selector(bar &)')
// false

This seems problematic if the plan is to relax the syntax somewhere in the future.

@bramus
Copy link
Contributor
bramus commented Feb 27, 2023

# Safari TP doesn't seem to work at all :

CSS.supports('selector(&)')
// false

Hmm, that looks like a bug to me, given Safari TP does support that selector. Searching the WebKit bug tracker, I found this bug filed for it: https://bugs.webkit.org/show_bug.cgi?id=252301


# There is also no way to detect support for the even more relaxed syntax where selectors can start with an identifier.

If one could nest inside of selector(), it would be possible:

CSS.supports('selector(div { span })');

I think this shortcoming should be plugged.

@romainmenke
Copy link
Member

Chrome is shipping nesting in ±2 weeks.
This issue seems important to give some extra thought before then.

Especially : #8399 (comment)

There is also no way to detect support for the even more relaxed syntax where selectors can start with an identifier.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-conditional-5][css-nesting-1] Feature detection for nesting.

The full IRC log of that discussion <fantasai> astearns: Something shipped in Chrome that's not quite what we want, but not clear on what we want
<fantasai> ... we should have had a good story before shipping anything
<fantasai> TabAtkins: I agree that this being parsable before shipping was ready was a mistake, but I don't think we can fix retroactively
<fantasai> ... don't think we should expose whether nesting is possible or not
<fantasai> astearns: we shouldn't have feature detection?
<fantasai> TabAtkins: we shouldn't add anything except selector detection, it'll just misfire on some versions of Chrome/Safari
<fantasai> plinss: wasn't there discussion of using & in other places?
<matthieudubet> q+
<fantasai> TabAtkins: allowing it elsewhere, yes, but concurrent with Nesting being supported
<fantasai> plinss: is that guaranteed?
<fantasai> TabAtkins: In practice yes
<fantasai> plinss: but it's usable in another feature that's not dependent on Nesting
<fantasai> TabAtkins: only @scope, but it's also nesting rules ...
<emeyer> fantasai: That’s different from the nesting feature because @scope can only contain nesting rules
<fantasai> TabAtkins: don't think ti's a problem in practice
<astearns> ack matthieudubet
<fantasai> matthieudubet: for feature detection, should we try to give the proper result with a selector
<fantasai> s/selector/relative selector/
<fantasai> matthieudubet: should @supports be aware of the nesting stack?
<plinss> q+
<fantasai> matthieudubet: and always return true/false regardless of nesting stack?
<fantasai> TabAtkins: the latter. @supports shouldn't be aware of where it is in the stylesheet
<TabAtkins> .foo { @supports selector(&) {...}}
<fantasai> TabAtkins: that should not give different results at the top level vs nested
<fremy> .foo { @supports selector(+a) {...}}
<fantasai> matthieudubet: & is allowed both places, but relative selectors are allowed or not depending on whether nested
<fantasai> TabAtkins: I would prefer we don't make @supports context-sensitive
<fantasai> TabAtkins: right now we don't carry context into the querying APIs, and you can't express that in JS
<fantasai> ... so as much as possible I'd like to keep those consistent
<fantasai> matthieudubet: Right now for Safari, it does take context into account
<fantasai> ... so if the selector is not supported *there* it'll return false
<TabAtkins> CSS.supports()
<fantasai> TabAtkins: what about CSS.supports()?
<fantasai> TabAtkins: the JS API can't know the context
<fantasai> matthieudubet: That's what we do for the at-rules. For JS API, we do the same, so when you write a relative one will always say false
<fantasai> ... because not in a nested context
<fantasai> TabAtkins: that interpretation is novel, and not expressed in the spec right now
<fantasai> ... if we want to do that, can you raise an issue?
<fantasai> ... new issue, please; this is unrelated to the current issue
<fantasai> astearns: It's better to have specific issues on narrow problems
<astearns> ack plinss
<fantasai> ... so agree we should have a separate issue on whether relative selectors inside @supports are context-sensitive
<fantasai> plinss: Important that nesting be readily detectable at the top level
<fantasai> ... I have concerns about feature detection of one feature being dependent on another feature
<fantasai> ... just because we implemented & and nesting together is cute, but not something to rely on
<emilio> But agreed nesting should def. be detectable in top-level and CSS.supports
<fantasai> fremy: If you want o feature-detect @scope, how do you do it?
<fantasai> plinss: how do I detect & for @scope?
<fantasai> TabAtkins: at-supports API doesn't yet allow querying that sort of thing
<fantasai> plinss: we need reliable support detection for nesting, that works reliably for @import supports().
<fantasai> ... so & detection is not good enough
<fantasai> TabAtkins: currently can only express as selector(&), if you want something more specific need a new thing
<fantasai> plinss: that needs to ship with Nesting
<fantasai> astearns: any suggestion of what this might look like?
<fantasai> plinss: @nest?
<fantasai> fremy: how about we check whether & is a valid property? That would be checking for nesting
<fantasai> ... e.g. @supports (&) { ... }
<heycam> @supports rule(p { & { } })
<fremy> @supports (&{})
<bradk> @supports (nesting) { … }
<fantasai> TabAtkins: that's not valid property
<fantasai> TabAtkins: maybe not that bad given how messy the shipping has been with this feature, but in general want to avoid special casing
<fantasai> plinss: We might want a general feature() function for things that are hard to feature-detect
<emeyer> fantasai: I think Francois’s suggestion does fit the current syntax
<emeyer> …That said, if we do allow that, we’ll be allowing any kind of selector-based rule that can be nested to be in there
<emeyer> …Might be more parsing than we want, but not inconsistent
<fantasai> TabAtkins: Depends if you think of it as () parses a declaration or if () parses "stuff that could go in a declaration block"
<fantasai> plinss: Would be a problem if we allow selectors, since range of selectors is open-ended
<fantasai> ... what if we add a div property
<fantasai> fremy: same problem we have today already
<fantasai> fremy: To me, I think it's a nice extension, doesn't require a big change
<fantasai> ... not saying we have to do it, it's just an idea
<fantasai> TabAtkins: can we do the rest of the design work in the thread? we have 9 min on the most important isseu
<fantasai> astearns: Sounds to me that for this issue, we're going to retain the bare & supports strategy in the spec, but might also add something that is a little more complex or specific?
<fantasai> TabAtkins: think so
<fantasai> astearns: so leave discussion here, don't need a resolution since selector(&) aready works
<fantasai> ... but will leave this issue open for further discussion of supports functionality
<fantasai> plinss: I believe it's very important that we have a stable and reliable mechanism before we ship anything, can we agree on that
<fantasai> TabAtkins: I think it's a good idea, I'm not going to commit to it
<fantasai> plinss: I think shipping this whithout reliable feature detection is a huge mistake
<fantasai> +!
<fantasai> +1
<fantasai> astearns: agree with plinss
<emeyer> +1
<bradk> Me too
<fantasai> astearns: I think we should have another breakout on Nesting next week

@SebastianZ
Copy link
Contributor Author

plinss: I believe it's very important that we have a stable and reliable mechanism before we ship anything, can we agree on that
TabAtkins: I think it's a good idea, I'm not going to commit to it
plinss: I think shipping this whithout reliable feature detection is a huge mistake

I totally agree with @plinss here. I fear, Google's strategy for shipping nesting without proper support for feature detection will have negative effects. Without a proper mechanism for feature detection, nesting is doomed to either not being adopted or to cause pages to break.

As @romainmenke pointed out earlier, the main issue is that browsers never implemented @import "..." supports();. Without that, authors don't have a global switch for browsers with nesting support and those without. And nesting support can only be checked when wrapping specific rules in @supports selector(&) { ... } within a stylesheet.
Unfortunately, using @supports in this case mainly means unnecessarily bloating the stylesheet because authors have to provide the same rules twice for browsers with and without support. I.e. they have to wrap every nested rule in @supports selector(&) { ... }. And for browsers that don't support nesting they need to add another @supports not selector(&) { ... } section basically duplicating their rules.

@bramus

In practice, though, I don’t think authors will test nesting, as they’ll simply see the nested styles not get applied in that case:

* Build a base style layer that doesn’t use nesting

* Layer nested styles on top

As outlined above, layering nested styles on top of not nested ones is not really a use case. Authors normally want to apply the same rules independently of how they are written.

Coming back to the issue outlined by @romainmenke, I believe, the main issue is allowing nesting while being backwards compatible and avoid putting the burden onto users.
That means, we need a way for UAs that support nesting to somehow suppress importing external stylesheets. Only when that's possible, nesting can really be used by authors without disadvantages.

Sebastian

@bramus
Copy link
Contributor
bramus commented Apr 11, 2023

# The CSS Working Group just discussed [css-conditional-5][css-nesting-1] Feature detection for nesting.

< heycam> @supports rule(p { & { } })
< fremy> @supports (&{})
< bradk> @supports (nesting) { … }

I like @heycam’s suggestion here to be able to pass an entire rule-set into @supports. Of the three suggestions, it has the widest coverage.

This would help not only here with nesting, but also cover future/other CSS features such as @scope, as authors can pass in @scope (.foo) to (.bar) { & { color: hotpink; } } to detect if that specific syntax is supported or not. Using a keyword like nesting doesn’t cover that.

This extension to @supports would pair really nicely with @import … supports(…) (suggested by @plinss above) and link[media="supports()"] (something that was discussed for Cascade Layers).

This extension to @supports doesn’t seem mandatory to be able to detect nesting though, as passing selector(&) will cover “is nesting supported?” just fine as the reality is that nesting and & ship together. Yes, some pre-release versions of Chrome/Safari incorrectly claim (or don’t claim) support for &, but given that these are pre-releases or versions that require the user to enable a feature flag, I think it’s safe to assume that users of those versions update their browsers very often.

@romainmenke
Copy link
Member

Yes, some pre-release versions of Chrome/Safari incorrectly claim (or don’t claim) support for &, but given that these are pre-releases or versions that require the user to enable a feature flag, I think it’s safe to assume that users of those versions update their browsers very often.

It wasn't a pre-release version of Chrome that incorrectly claimed to support & :)

There also isn't a way to differentiate between what shipped in Chrome 112 and the highly likely direction of the specification :

// In Chrome 112
CSS.supports('selector(&)')
// true
CSS.supports('selector(& div)')
// true
CSS.supports('selector(div &)')
// true

Ideally authors have a reliable way to detect support for the final version of nesting, even in older versions of Chrome.

@bramus
Copy link
Contributor
bramus commented Apr 12, 2023

It wasn't a pre-release version of Chrome that incorrectly claimed to support & :)
True. There’s a workaround – which covers all browsers – I mentioned before, but admittedly it’s a nasty hack.

There also isn't a way to differentiate between what shipped in Chrome 112 and the highly likely direction of the specification

If more robust/reliable feature detection through < method-this-issue-settles-on > lands, Chrome 112 wouldn’t support that new detection method, so it would still get the non-nested styles because it has a more limited nesting support.


Rewinding a bit. Say the suggested @import … supports(…); lands. Currently using those statements in any browser does not load any of the referenced CSS files, as they don’t understand the statements.

@import "nested-and-small.css" supports(<method-to-detect-nesting>);
@import "not-nested-and-large.css" not supports(<method-to-detect-nesting>);

That means, the snippet above won’t cut things here:

  • Browsers that support @import … supports(…); + nesting will load nested-and-small.css.
  • Browsers that don’t support @import … supports(…); will load none of those files.

What is parseable is, is this … but then you’d end up with double loads + competing stylesheets in browsers that do support @import … supports(…);

@import "not-nested-and-large.css";
@import "nested-and-small.css" supports(<method-to-detect-nesting>);

Not sure how this could be solved in a nice way 🤔

@romainmenke
Copy link
Member

Correct, although browsers do download all stylesheets, even when they ignore them.
Bandwidth usage is roughly doubled for end users and they still have a broken page.


Some browsers maybe don't intend to ship nesting support in the sort term.
These could add support for @import … supports(…);. This makes it possible to have a transition period where some browsers have nesting support "now" and others only "later".

It doesn't help all users of older browser versions but it might still be a useful tool.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-conditional-5][css-nesting-1] Feature detection for nesting.

The full IRC log of that discussion <fantasai> astearns: We have a feature-detection story, question is how to detect browsers that support nesting vs don't support nesting?
<dbaron> astearns: Is that what's remaining in this issue?
<fantasai> TabAtkins: unsure... someone else should take this
<fantasai> SebastianZ: We need some way to migrate and have fallbacks for old browsers
<fantasai> SebastianZ: so the question is how to allow feature-detection, and at the same time do it so that all the browsers don't fail completely
<fantasai> SebastianZ: Of course they don't support nesting, but we need some way to handle that case
<fantasai> ???: We need more than just selector(&)?
<dbaron> s/???/matthieu/
<astearns> s/???/matthieu/
<fantasai> SebastianZ: selector(&) does work, but it focuses on style rules. Doesn't target whether other rules can be nested, or media rules, or something else
<fantasai> astearns: Given that we have not much time yet, does it make sense to continue the discussion of this upgrade strategy in this issue, or should there be a separate issue just on the path we want authors to take when they don't know whether the browsers supports nesting or not?
<fantasai> SebastianZ: I think there's an issue targetting the author experience... not sure which one it was
<fantasai> astearns: Since this feature is titled Feature Detection, should we close this issue and find or create an issue about the author experience?
<fantasai> SebastianZ: Hard to say
<fantasai> SebastianZ: you want feature detection for author so that they can migrate to nesting, so they're both entangled
<fantasai> ACTION: astearns to find path forward for this author-experience issue, whether to continue with this issue or make a new one

@astearns astearns removed the Agenda+ label Apr 19, 2023
@SebastianZ
Copy link
Contributor Author

Summarizing the remaining parts:

  1. Feature detection of nesting beyond style rules
  2. Avoid double-loading stylesheets for browsers that do support nesting and feature detection

The first poing still directly refers to this issue. For the second point I can create a separate issue.

Sebastian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-conditional-5 Current Work css-nesting-1 Current Work
Projects
None yet
Development

No branches or pull requests