Csswg-drafts: [css-conditional-4] Feature detection for descriptors

Created on 22 Mar 2018  Â·  16Comments  Â·  Source: w3c/csswg-drafts

Currently, @supports and CSS.supports only support property: value pairs. The only way for web developers to detect support for a certain descriptor in an at-rule is to use JavaScript. For example:

let e = document.createElement("style");
e.textContent = "@font-face { font-display: swap; }";
document.documentElement.appendChild(e);
let isFontDisplaySupported = e.sheet.cssRules[0].cssText.indexOf("font-display") != -1;

(from https://bugzilla.mozilla.org/show_bug.cgi?id=1296373#c6)

It would be good if CSS can test whether a user agent supports a descriptor: value pair.

See also a related issue in Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=600137

Tagged as "unknown/future spec" for now, because I'm not sure if we should extend @supports (which is in css-conditional), or develop a new mechanism for it.

css-conditional-4

Most helpful comment

It'd be nice to have this for @property so we could feature detect the support from CSS directly with something like:

  @supports descriptor(@property, syntax: "<color>") { ... }

All 16 comments

I agree that being able to detect descriptor support is valuable. I would have thought it belongs in CSS Conditional.

Yeah, it's Conditional - this is precisely why we took care to include arbitrary functional terms in the @supports grammar which resolve to unknown, so we can add more types of support-testing in the future.

(Need to also be able to test for types, like if "1foo" is a <length>, etc.)

Something like @supports descriptor(@media, font-display: block) { ... }.

@tabatkins Did you mean to write:

@supports descriptor(@font-face, font-display: block) { ... }

(Need to also be able to test for types, like if "1foo" is a , etc.)

Maybe. We have a clear syntax extension path if we want to, but why do we need to test if 1foo is supported independently of testing if bar: 1foo is supported?

Did you mean to write:

Yes, I did mean that.

Maybe. We have a clear syntax extension path if we want to, but why do we need to test if 1foo is supported independently of testing if bar: 1foo is supported?

Yeah, one could do that, but given that UAs will have explicit parsers for each value type for Typed OM purposes, we'll be able to expose that directly, if it makes one's intent clearer.

Sure, but when you want to use a value, you're going to use it somewhere. And it is possible that the UA supports that value without supporting it where you planned to use it.

For instance, a newer version of a property may accept % and length while the old one only took %. The browser you're in does not yet support the length version yet, but does support the new fancy length unit you want to use in places where it does support length.

In that sense, while @supports unit(1ch) would something that is technically true, it seems a bit of a footgun: @supports unit(1ch) { prop-that-used-to-take-percent-only: 1ch; }

The unit(…) function could only be exposed from within CSS.supports(…) but not from @supports, that would solve the footgun issue while allowing developers to test for unit support from JavaScript, also the unit(…) function is off‑topic and should be discussed in a separate issue.

It'd be nice to have this for @property so we could feature detect the support from CSS directly with something like:

  @supports descriptor(@property, syntax: "<color>") { ... }

It'd be nice to have this for @property so we could feature detect the support from CSS directly with something like:

  @supports descriptor(@property, syntax: "<color>") { ... }

Yeah, @property urgently needs this feature, Chrome is ready to ship: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/3ygpsew53a0

Especially in [css-properties-values-api] currently implemented by Chrome, syntax: '<image>' is not yet supported, which makes it difficult to detect it. cc @andruud

I like the @supports descriptor() proposal. However, I'm not sure if it covers the @property use-case. The syntax descriptor in particular accepts any <string> parse time, so simply checking if there's a parse error (like we do in other @support cases) won't be enough. Probably each descriptor would need to define how to behave when used in a @supports descriptor().

I also wonder if there are any traps regarding some descriptors depending on other descriptors. For example, the following is hard to evaluate if we don't also know the syntax:

@supports descriptor(@property, initial-value: 1em) { ... }

For syntax "*" it's valid, but for e.g. "<length>" it's not.

It's syntactically valid in either case, we would just invalidate the rule as a whole if syntax wasn't a compatible value. So that would resolve to true. (We don't, and can't, make declaration parsing validity dependent on other declarations, not least because the relevant "other declaration" might come after the one in question.)

Of course, but my point was that checking for parsing validity alone isn't enough to do what people (/ @yisibl) want for @property. :slightly_smiling_face:

For example @supports descriptor(@property, syntax: "<image>") { ... } would be true in Chrome, even though <image> syntax is not implemented.

Hm, that's true. Validity of syntax does depend on us parsing the string, so if you wrote gibberish it would be thrown out as invalid. Seems like we could similarly test for validity of non-terminals in the string? That's information known at parse-time, certainly. I'll open an issue on the correct spec so we're not clogging up this issue. ^_^

Editted to add: wait no that's not the case, it does check for known non-terminals. The problem is just that we don't support the "<image>" non-terminal, but the spec doesn't have an allowance for "only recognize the ones you actually support". That seems much more straightforward of an obvious bug-fix, so I'll just do that.

Was this page helpful?
0 / 5 - 0 ratings