w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.43k stars 657 forks source link

[css-fonts-4][css-nesting] Nesting of @supports inside @font-face and font technology feature queries #6520

Closed LeaVerou closed 2 years ago

LeaVerou commented 3 years ago

This is related to #633 and this part of css-fonts-4: https://drafts.csswg.org/css-fonts-4/#font-face-src-parsing

A bit late to the party, but I wondered: what if, instead of adding yet another microsyntax for feature detection, we use @supports with an appropriate font-technology() function (or whatever we want to name it)?

We recently resolved to allow nesting of conditional rules inside regular rules, so that authors can do things like:

a {
    color: red;

    @supports (foo: bar) {
        color: green;
    }
}

What if this was allowed in @font-face as well? That way, authors could do something like:

@font-face {                                                                                                                                        
    font-family: Foo;
    src: url("foo.woff2") format("woff2");

    @supports font-technology(variations) and font-technology(COLR) and font-technology(palettes) {                                                                                                                                         
        src: url("foo.woff2") format(woff2);
    }
}

or

@font-face {                                                                                                                                        
    font-family: Foo;
    src: url("foo.woff2") format("woff2");

    @supports font-technology(variations COLR palettes) {                                                                                                                                       
        src: url("foo.woff2") format(woff2);
    }
}

instead of:

@font-face {                                                                                                                                        
    font-family: Foo;
    src: url("foo.woff2") format("woff2");                                                                                                                                          
    src: url("foo.woff2") format(woff2 supports variations color(COLR) palettes);                                                               }

Benefits:

Downsides:

Unlike conditional rules in general, feature queries do not change during the lifetime of the page load, and thus this should not trigger re-interpretation of the @font-face rule or be more heavyweight in any other substantial way.

If such syntax is used with today's browsers, they drop the @supports rule but keep the @font-face rule, so it does appear forwards compatible. testcase

There are no implementations of the current syntax, so it may not be too late for the change.

Thoughts, @svgeesus @litherum @fantasai @tabatkins?

svgeesus commented 3 years ago

This seems obvious but checking just in case: your proposal @LeaVerou is to allow @supports inside any at-rule that has descriptors (so, not @charset for example), not solely on @font-face, right?

LeaVerou commented 3 years ago

Currently it is for @font-face. Obviously, it would be better to allow it in every at-rule, but I didn't want some unlikely combination of at-rule and @supports to hold up this proposal, so I figured we could start small and expand as use cases arise.

drott commented 3 years ago

CC @jfkthame

I'll investigate what that would entail from an implementation point of view (complexity, overhead) and comment once I have some findings.

One consideration from a readability point of view: If we introduce such a @supports rule, we will have both mechanisms: a list of entries in the src: descriptor (for example multiple url() entries potentially then "legacy" format("...") specifiers (with its own semantics of choosing the first compatible one from this list) and potentially multiple src: descriptors conditional on @supports blocks in the same @font-face rule, which I personally do not find great for consistency or readability. In other words, we would change the primary paradigm for src: selection to the @supports syntax but would still need to keep compatibility with the current approach of traversing a list of entries.

FWIW, the "parsing weirdness" may be considered addressed or improved with the most recent change which references the CSS syntax spec for parsing a comma separated list of components.

emilio commented 3 years ago

How is the supports rule represented in the OM? Implementation-wise I think it'd be easier for us if it just disappeared, but...

LeaVerou commented 3 years ago

Hi @drott!

One consideration from a readability point of view: If we introduce such a @supports rule, we will have both mechanisms: a list of entries in the src: descriptor (for example multiple url() entries potentially then "legacy" format("...") specifiers (with its own semantics of choosing the first compatible one from this list) and potentially multiple src: descriptors conditional on @supports blocks in the same @font-face rule, which I personally do not find great for consistency or readability. In other words, we would change the primary paradigm for src: selection to the @supports syntax but would still need to keep compatibility with the current approach of traversing a list of entries.

Yeah, this was raised by @plinss as well. The counter-argument he agreed to was that @supports came after format(), so while we're stuck with format() for legacy format selection, we shouldn't be actively developing two different feature detection mechanisms, one of which is entirely ad hoc and severely more limited.

FWIW, the "parsing weirdness" may be considered addressed or improved with the most recent change which references the CSS syntax spec for parsing a comma separated list of components.

I was referring to the fact that this descriptor's syntax needs prose and cannot be fully described by a grammar. I wasn't even aware that it used to be even weirder, whoa!

@emilio

How is the supports rule represented in the OM? Implementation-wise I think it'd be easier for us if it just disappeared, but...

I've wondered about this too, but I'm afraid making it disappear would be fairly inconsistent with every other @-rule, which would be even more confusing once Nesting is implemented.

tabatkins commented 3 years ago

While it would involve more duplication, would it be okay to just leverage @supports normally, with some new queries to ask about various font-feature support, and then just have @font-face as a child of the rule like normal?

The big argument against is if we think multiple independent queries affecting different bits would be common; you'd have a combinatorial explosion to achieve equivalent results.

tabatkins commented 3 years ago

Looking at the proposal itself - it feels slightly weird to have context-specific @supports (I presume this wouldn't allow arbitrary property-support queries, but only font-based ones?). If I'm wrong about that and this would just be an ordinary @supports, with a supporting proposal to add the font-feature queries, then this is less weird. (If I'm right, naming it @font-supports or something would defuse my objection.)

I don't have a strong opinion on whether this should be treated as a parse-time syntax, disappearing from the tree in the OM, or kept around like normal @supports is. Parse-time is definitely simpler overall, but I understand how it feels new and odd.

Overall tho, I definitely support something like this over the growing weird microsyntax. The microsyntax was reasonable when it was just one thing, but it's getting out of hand.

LeaVerou commented 3 years ago

While it would involve more duplication, would it be okay to just leverage @supports normally, with some new queries to ask about various font-feature support, and then just have @font-face as a child of the rule like normal?

The big argument against is if we think multiple independent queries affecting different bits would be common; you'd have a combinatorial explosion to achieve equivalent results.

I think that could be a good first step, and would enable authors to do what they want with some duplication, and would likely (?) be relatively easy to implement. However, we do eventually want to avoid the duplication, even if multiple independent queries aren't common.

Looking at the proposal itself - it feels slightly weird to have context-specific @supports (I presume this wouldn't allow arbitrary property-support queries, but only font-based ones?). If I'm wrong about that and this would just be an ordinary @supports, with a supporting proposal to add the font-feature queries, then this is less weird. (If I'm right, naming it @font-supports or something would defuse my objection.)

It is not context-specific. The whole idea is that this way authors can use it to feature detect in any context that suits them, not just to differentiate the src, but possibly other aspects of their style.

drott commented 3 years ago

Having looked at and discussed with my CSS colleagues, the implementation of @supports inside the @font-face at-rule would be a larger effort, in particular if the @supports rules need to be represented in the CSSOM, which poses problems given the current internal representation. (In addition, we're blocked on some parser refactoring which would make this more difficult, but that's an internal issue).

While it would involve more duplication, would it be okay to just leverage @supports normally, with some new queries to ask about various font-feature support, and then just have @font-face as a child of the rule like normal?

I think that could be a good first step, and would enable authors to do what they want with some duplication, and would likely (?) be relatively easy to implement. However, we do eventually want to avoid the duplication, even if multiple independent queries aren't common.

Yes, I agree, adding something similar to a <supports-font-technology-fn> to 2. Extensions to the @supports rule with syntax similar to what is in the current font spec proposal is immediately useful for the desired feature detection through CSS.supports() JavaScript and would immediately work at the top level (not nested).

This would give us a path that's relatively straight-forward to implement and not blocked on nesting @supports inside @font-face, while it would still allow for that kind of nesting later and migrating away from unnecessary @font-face repetition.

LeaVerou commented 3 years ago

I think adding the @supports criteria first, and implementing the nesting step later is a good path forwards.

Adding this to the agenda so we can resolve that these changes have CSS WG consensus.

drott commented 3 years ago

In this branch I drafted an edit to css-conditional-4, carrying over the syntax from fonts-4's - Parsing the source descriptor, an excerpt from that draft (feel free to comment on the commit directly as well):

<supports-feature> = <supports-selector-fn> | <supports-font-technology-fn> | <supports-decl>
<supports-selector-fn> = selector( <complex-selector> )
<supports-font-technology-fn> = font-technology ( <font-technology> )
<font-technology> = [ features( <font-feature-technology> ) | variations
                    | color( <color-font-technology> ) | palettes | incremental ]
<font-feature-technology> = [ opentype | aat | graphite]
<color-font-technology> = [ COLRv0 | COLRv1 | SVG | sbix | CBDT ]

Considerations:

I'd be very happy if in tomorrow's meeting we could attempt to resolve towards a direction of the syntax along those lines (feedback very welcome), in addition to the general aim to resolve adding the criteria to the @supports rule.

svgeesus commented 3 years ago

I did not add a repetition operator # after in the rule as required combinations of technologies can be expressed through and and or of the @supports syntax, which I consider an improvement over the syntax in the fonts spec.

I agree, more readable that way.

svgeesus commented 3 years ago

Just to be sure I understand, the first example in the@font-face src explainer would become (repetitive, but readable; most desirable option is last):

/* 1. prefer COLRv1, then SVG-in-OpenType, then COLRv0 */
@font-face {
  font-family: jewel;
  src: url(boring.ttf) format("woff2");
}
@supports  font-technology(color(COLRv0)) {
    @font-face {
        font-family: jewel;
        src: url(jewel-v0.woff2) format("woff2");
    }
}
@supports  font-technology(color(SVG)) {
    @font-face {
        font-family: jewel;
        src: url(jewel-svg.woff2) format("woff2");
    }
}
@supports  font-technology(color(COLRv1)) {
    @font-face {
        font-family: jewel;
        src: url(jewel-v1.woff2) format("woff2"),;
    }
}
drott commented 3 years ago

Yes, that's how I would express it as well. That is: for now, without nested @supports.

svgeesus commented 3 years ago

@dbaron @fantasai thoughts? Since we are all editors of Conditional 3 I assume we are of Conditional 4 too, right? @astearns @atanassov or would that need a separate resolution?

svgeesus commented 3 years ago

Oh wait

The declaration being tested must always occur within parentheses, when it is the only thing in the expression. source

So that is like

@supports  (font-technology(color(COLRv0))) {
   and so on
LeaVerou commented 3 years ago

Oh wait

The declaration being tested must always occur within parentheses, when it is the only thing in the expression. source

So that is like

@supports  (font-technology(color(COLRv0))) {
   and so on

This applies to declaration tests, not selector() or font-technology() queries.

Nitpick, I don’t think we need nested function calls, not to mention color() might look confusing because of the other color() function. We could just prefix keywords with color- and feature-, which avoids the multiple nested parens.

drott commented 3 years ago

We could just prefix keywords with color- and feature-, which avoids the multiple nested parens.

Updated the proposed change with that suggestion, thanks.

LeaVerou commented 3 years ago

@svgeesus asked yesterday if we could use colons (font-technology(color: COLRv0)). I think that's not idiomatic to CSS and it's weird to have key-value pairs for some things and not others, but I'd defer to @tabatkins on that one. If he's ok with colons, I’m ok with colons.

svgeesus commented 3 years ago

So, that would be

/* 1. prefer COLRv1, then SVG-in-OpenType, then COLRv0 */
@font-face {
  font-family: jewel;
  src: url(boring.ttf) format("woff2");
}
@supports  font-technology(color-COLRv0) {
    @font-face {
        font-family: jewel;
        src: url(jewel-v0.woff2) format("woff2");
    }
}
@supports  font-technology(color-SVG) {
    @font-face {
        font-family: jewel;
        src: url(jewel-svg.woff2) format("woff2");
    }
}
@supports  font-technology(color-COLRv1) {
    @font-face {
        font-family: jewel;
        src: url(jewel-v1.woff2) format("woff2"),;
    }
}
svgeesus commented 3 years ago

it's weird to have key-value pairs for some things and not others

Its also weird to have key-value pairs multiple times for the same key

@supports font-technology(color: COLRv0) AND font-technology(color: COLRv1)

so on balance I prefer the hyphenated form proposed earlier.

litherum commented 3 years ago

One note of caution - we have to consider how authors will achieve progressive enhancement on new browsers, while continuing to make their page work on old browsers. So, if we do something like this, it's more likely authors will be saying something like

@font-face {
    font-family: jewel;
    font-weight: 400;
    src: url(jewel-fallback.woff2) format("woff2");
}
@supports font-technology(color-COLRv1) {
    @font-face {
        font-family: jewel;
        font-weight: 400;
        src: url(jewel-v1.woff2) format("woff2");
    }
}

(I added the font-weight descriptor, because it's not unreasonable to do so, and it helps inform the below point.)

This behaves differently than the existing progressive enhancement behavior of the src descriptor:

@font-face {
    font-family: jewel;
    src: url(jewel-fallback.woff2) format("woff2");
    src: url(jewel-v1.woff2) format("woff2" supports(COLRv1)), url(jewel-fallback.woff2) format("woff2");
}

In the second example, if the browser doesn't understand the new syntax, ~or "COLRv1",~ the entire src line falls back wholesale (Edit: and if the browser doesn't understand "COLRv1", just that item in the src descriptor is ignored). However, in the first example, the browser would see both @font-face declarations together.

If the second @font-face declaration has exactly the same descriptors, it will shadow the first one, and all is good (Edit: all is not good, see below). But, if the second one has a typo, the author has suddenly made a family with 2 fonts, and it's possible of half or even all of their text erroneously gets rendered with the wrong font.

css-meeting-bot commented 3 years ago

The CSS Working Group just discussed nesting of @supports inside @font-face.

The full IRC log of that discussion <TabAtkins> Topic: nesting of @supports inside @font-face
<TabAtkins> github: https://github.com/w3c/csswg-drafts/issues/6520
<TabAtkins> leaverou: A little background, in the TAG review request the current syntax is extending the format() syntax for 'src'
<lea> https://github.com/w3c/csswg-drafts/blob/main/css-fonts-4/src-explainer.md#use-case-3-detectability
<TabAtkins> leaverou: It hasn't been implemented yet; Chrome is keen to implement quickly
<TabAtkins> leaverou: In the TAG we recognized the use-case, but were concerned about a new microsyntax when @supports alreayd exists
<TabAtkins> leaverou: So was thinking about how we could utilize @supports, and posted this issue
<chris> Explainer for current src descriptor https://github.com/w3c/csswg-drafts/blob/main/css-fonts-4/src-explainer.md
<TabAtkins> leaverou: Two things. First, adding a new @supports query for detecting font tech.
<TabAtkins> leaverou: Lets authors differentiate their CSS in other places; existing proposal only lets them use it when selecting font source.
<TabAtkins> leaverou: Could imagine authors wanting different CSS for a monochrome vs color font
<drott> q+
<TabAtkins> leaverou: This also makes it much easier to programmatically detect, vs doing rule hacking and seeing if there is a syntax error
<TabAtkins> leaverou: Google said they could add the font-tech queries in @supports easily
<TabAtkins> leaverou: Second bit is to let @supports nest inside of @font-face, extending the Nesting proposal
<TabAtkins> leaverou: But that would be a more substantial request
<TabAtkins> leaverou: So proposal is just to add the @supports queries for now - it does the job, if a bit clunky. And in the future perhaps do the nesting thing.
<Rossen_> ack drott
<TabAtkins> drott: Good summary. I'd support font-tech queries in @supports
<chris> q+
<TabAtkins> drott: And am open to later improving it by integrating Nesting, but the immediate benefit is just feature detection, so the @supports queries works for me.
<emilio> q+
<TabAtkins> drott: I've made a syntax proposal for Conditional 4 to support this
<Rossen_> ack chris
<TabAtkins> chris: I wrote an explainer for it
<TabAtkins> chris: [missed due to chop]
<drott> 👍
<TabAtkins> chris: TAG asked for an explainer; having written it, it was clear the only benefit of the existing syntax is that old browsers would parse without falling over
<TabAtkins> chris: It has no other redeeming features. It's an ugly complex microsyntax and is hard to read
<Rossen_> q?
<TabAtkins> chris: I think using @supports makes sense even if we can't use it directly in @font-face
<TabAtkins> chris: We've got some examples in the thread and I think it reads easily
<TabAtkins> emilio: I like this
<myles> q+
<Rossen_> ack emilio
<TabAtkins> emilio: Only question is if there's another place we need to parse this font stuff?
<chris> q+
<TabAtkins> emilio: To avoid the "specialized parser" thing that we try to avoid with @supports
<fantasai> TabAtkins: while trying to avoid specialized parse is a general goal
<fantasai> TabAtkins: we recognized there will be cases where we do
<fantasai> TabAtkins: as long as we're carefully scoped wrt feature queries that are not just parsing-based, should be OK
<TabAtkins> myles: One question - if an author uses @supports, is there a way to say "else"?
<TabAtkins> myles: If there's not a way to do that... @font-faces join together to form a family, rather than overriding
<Rossen_> q?
<Rossen_> ack myles
<TabAtkins> emilio: Can use "not"?
<TabAtkins> myles: "not" is both "fails the query" and "doesn't understand"
<TabAtkins> chris: Usual fallback is to put something normal outside, then override in a @supports
<TabAtkins> myles: Right, that's problematic; if it's supported it'll define a combined family using both @font-face rules.
<TabAtkins> myles: Author probably wants it to override
<drott> q+
<TabAtkins> myles: If they're careful they might override, like all same weight/etc, but if they didn't they'll both be present
<lea> q+
<chris> q+
<TabAtkins> q+
<fantasai> myles: and they will join together to form a family
<fantasai> myles: if descriptors aren't identical, might end up using both fonts in the page instead of only the second one
<chris> q-
<TabAtkins> chris: we already have this thing where font faces can combine together into a family, that's be design
<fantasai> TabAtkins: he's saying that conflicts with the author's design here.
<TabAtkins> myles: Right, if you have the non-conditional outside and the conditional inside, that's brittle
<emilio> TabAtkins: this is a general problem with a lot of things
<emilio> ... we don't have an answer to negate a query, but there's a proposal for an "else" on conditional rules
<dbaron[m]> some of these problems seem specific to @font-face inside @supports rather than @supports inside @font-face
<lea> q?
<fantasai> +1 dbaron[m]
<emilio> ... if there's implementor interest I'd be happy to revive it
<TabAtkins> https://tabatkins.github.io/specs/css-when-else/
<Rossen_> ack TabAtkins
<emilio> myles: I think there isn't a lot of sense to build the stopgap solution on something that doesn't exist yet
<TabAtkins> myles: If the oracle delivered us some way of having an else attached to @supports tomorrow, that woudl solve the problem
<chris> q+ to say format strings were a stopgap that lasted 2 1/2 decades
<TabAtkins> drott: I think this is an improvement over the current proposed syntax
<TabAtkins> drott: You're basing this on the concern on the likelihood of a typo; I think most will be coming from 3rd party fonts so that's not really a concern
<Rossen_> ack drott
<TabAtkins> drott: Second, in browsers where author expects font-tech(color) to work, "not" would work
<TabAtkins> myles: I think it would help if after this call we could have an example of the fallback
<chris> the issue already has such an example
<TabAtkins> lea: There's a snippet in the issue that Chris posted
<Rossen_> q?
<Rossen_> ack lea
<TabAtkins> leaverou: I think drott mentioned most points
<TabAtkins> leaverou: Reminder that this isn't *ideal* but it can be done quickly, and when we go on to nesting it'll work without duplication
<TabAtkins> leaverou: Also think ahving "else" in a conditional block would be super useful; it shouldn't hold this up tho.
<drott> +1 for not blocking on an else block
<TabAtkins> Agreed, fwiw
<Rossen_> ack dbaron[m]
<Zakim> dbaron[m], you wanted to react to lea
<TabAtkins> But happy to lean on this to grab impl support ^_^
<Rossen_> ack dbaron[m]
<TabAtkins> dbaron[m]: My understanding of myles' concern is - I think a lot applies if we have @supports { @font-face{}}, but a lot of the proposal is doing @font-face { @supports{}}, and I don't think the interaction concerns apply in that case
<Rossen_> q
<TabAtkins> myles: Right. I have different feedback in that case, but the proposal is currently the first case.
<lea> q?
<TabAtkins> fantasai: First, given myles' example, I do have concern about allowing this without inline/nested supports, becuase of his mentioned concerns
<lea> q+ to say that this problem actually exists today when defining font families, it's not new
<TabAtkins> fantasai: Second, it seems the proposal is to add font-technology() function which include some features that could be part of a font format, but it's not clear to me how that relates tot he font format
<drott> q+
<TabAtkins> fantasai: What if the browser supports colorv1 in woff2, but not others. Would we need to tie the feature query to a font format?
<Rossen_> ack fantasai
<drott> q-
<TabAtkins> chris: woff1 and woff2 are encodings of the same font tech (truetype)
<chris> 1. stopgap 2. OM complexity inside @font-face 3. making other stylistic changes based on font support 4. unrelated to formats
<Rossen_> ack chris
<Zakim> chris, you wanted to say format strings were a stopgap that lasted 2 1/2 decades
<TabAtkins> chris: The entire format string was a stopgap because we didn't have font mime types
<TabAtkins> chris: So "stopgap" is a non-argument in my mind
<TabAtkins> chris: If we do put @supports inside @font-face it complicates the OM; current proposal avoid that
<TabAtkins> chris: Using @supports doesn't just allow switching font, it lets you vary other aspects of your style
<TabAtkins> chris: Finally, the only reason supports were smuggled into format string is for parsing. But spec actually mandates OpenType and TrueType treated the same.
<TabAtkins> chris: So the font technology is almost completely orthogonal to the format used
<myles> q+ to respond to chris
<drott> q+
<TabAtkins> chris: So decoupling as this proposal does is a much clearner and nicer way
<chris> q?
<Rossen_> ack lea
<Zakim> lea, you wanted to say that this problem actually exists today when defining font families, it's not new
<myles> q-
<TabAtkins> lea: The concern myles brought up about typos is already existant; when authors write a family they could already typo and have the wrong family happen
<Rossen_> ack drott
<TabAtkins> drott: as lea mentioned, the reason we brought to the TAG is it seemed helpful to get some time of feature detection for COLR v1, so I hope we can have CSS support for that at the same time
<TabAtkins> Rossen_: I think the TAG feedback was clear - colr1 was gonna be a great addition
<chris> s/was/is/
<TabAtkins> Rossen_: Introducing new microsyntaxes is generally discouraged when we have existing feature-detect capabilities
<TabAtkins> Rossen_: I appreciate you ahve some impl urgency on your end. Important to get what's gonna stick for the future right tho.
<Rossen_> q?
<TabAtkins> Rossen_: So not sure I'm hearing the solution that addresses the current user needs and the tech being proposed
<chris> s/colr1/COLRv1
<TabAtkins> Rossen_: With two minutes remaining, unsure if we'll have a resolution
<TabAtkins> Rossen_: Propose we continue in the issue and bring this back next week for resolution
svgeesus commented 3 years ago

In the second example, if the browser doesn't understand the new syntax, or "COLRv1", the entire src line falls back wholesale.

No, that is actually the reason we went for that syntax - the second src (or the second comma-separated item, if you did it that way) is dropped but the first remains, so in older browsers you end up with


@font-face {
    font-family: jewel;
    src: url(jewel-fallback.woff2) format("woff2");
}
tabatkins commented 3 years ago

I don't really have an opinion on whether we do hyphenated values or use colon-separated syntax. While we don't quite have precedent for colons inside of a function, it's just a tiny step past paren-wrapped colon-separated values, so I'd be fine with it.

My only real complain is that font-technology() is so long. Can we just do font()?

litherum commented 3 years ago

It was brought up on today's call that we already have the typo problem, but I think that typo problem and this typo problem are different enough that they're worth distinguishing between.

If an author uses two font face blocks to create a family, their goal is to use both fonts and associate the fonts together, having them act as a single family. If the author makes a typo, the exact boundaries between the different faces in that family will be wrong, but they will still have achieved their general purpose - associate the fonts together and have them act as a single family.

In the situation in https://github.com/w3c/csswg-drafts/issues/6520#issuecomment-905691885, their goal is not to use both fonts or create a family; but instead to implement progressive enhancement on newer browsers. If they make a typo, they haven't achieved their general purpose; they've instead triggered a totally different kind of functionality, which can behave exactly the opposite of what they were intending to do in the first place.

Edit: I'm describing typos in the numeric descriptors: font-weight, font-stretch, and font-style.

jfkthame commented 3 years ago

In addition to the potential for unexpected behavior if the "preferred" rule does not precisely shadow the fallback, Myles's example above (repeated here for ease of reference):

@font-face {
    font-family: jewel;
    font-weight: 400;
    src: url(jewel-fallback.woff2) format("woff2");
}
@supports font-technology(color-COLRv1) {
    @font-face {
        font-family: jewel;
        font-weight: 400;
        src: url(jewel-v1.woff2) format("woff2");
    }
}

also conceals a performance footgun.

Consider the case of a browser that does implement COLRv1, so it is expected to use the jewel-v1.woff2 font. That seems fine.

What is perhaps not obvious to the author is what happens if the content styled with font-family: jewel includes a character that is not supported by jewel-v1.woff2. Because the jewel family contains two faces with identical style descriptors, when the browser finds a character missing from one of them, it will be expected to fall back to the other.

It's likely, of course, that the two jewel faces have the same character coverage, and falling back from jewel-v1.woff2 to jewel-fallback.woff2 is pointless, but the browser will nevertheless have to download the fallback resource and check its character coverage.

This could be avoided by careful use of unicode-range, so that any character that is not covered by the v1 font is known to be excluded from the fallback face as well, but this is an added burden for authors, and seems unlikely to be done with any consistency.

litherum commented 3 years ago

@svgeesus

No, that is actually the reason we went for that syntax

Yes, you're right, I've edited https://github.com/w3c/csswg-drafts/issues/6520#issuecomment-905691885 to strike out the incorrect text, and add some clarifying text.

LeaVerou commented 3 years ago

@litherum Could you provide a full example of the problem you’re seeing, i.e. not just the @font-face rules but the actual usage and the problem that occurs? It seems identical to me to the existing issue. In one case mistyping a descriptor gets you the wrong face, in the other case mistyping a descriptor gets you the fallback font, which is still part of the same family. 🤷🏼‍♀️

@jfkthame Interesting. Is that per spec or a browser bug? I could not actually find anything in css-fonts about this. Do note that instead of unicode-range (which would be a pain, I agree), one could also use not in @supports instead of having a bare @font-face as the fallback.

dbaron commented 3 years ago

I don't think what @jfkthame describes in https://github.com/w3c/csswg-drafts/issues/6520#issuecomment-905805384 is a bug at all. I think the design of @font-face is that each @font-face rule adds an entry to the library of font faces that can be used. So I think things that are designed to be modifications to a single face in that library probably belong inside of a single @font-face rule, whereas things that are designed to be separate faces should be in separate @font-face rules.

jfkthame commented 3 years ago

@jfkthame Interesting. Is that per spec or a browser bug? I could not actually find anything in css-fonts about this.

This falls naturally out of the font matching algorithm. Each @font-face rule (with the same font-family descriptor) adds an entry to the collection of faces that belong to the given family. Font matching will filter that collection according to the requested style properties, but if there are multiple faces in the family with the same weight/width/style, they'll all remain in the matched set (it's a "composite face"), and the browser has to use the "effective character map" (intersection of unicode-range and the font's actual coverage) to choose among them.

Note that existing sites rely on this behavior. A somewhat common "copy-inhibitiing" scheme is to pseudo-randomly split the glyphs of a font across two separate resources, so that each resource has a scattering of glyphs that are unlikely to be much use as a standalone font. The site then uses two @font-face rules to load both resources as the same font-family, with the same style descriptors, and relies on the browser selecting the appropriate one on a character-by-character basis.

(I'm not endorsing this practice: I think it's not particularly effective, hurts performance, and breaks things like kerning, but I see it in the wild.)

jfkthame commented 3 years ago

Do note that instead of unicode-range (which would be a pain, I agree), one could also use not in @supports instead of having a bare @font-face as the fallback.

Yes, using @supports not ... would avoid this. That gets a bit cumbersome in complex cases: e.g. if there are two or three color-font techologies being queried, as well as variations and a couple of shaping technologies, the @supports rule wrapping the fallback that doesn't support any of these could become pretty unwieldy.

It also feels like a footgun because it differs from how @supports normally interacts with graceful degradation. With typical CSS properties, the user can write the generic fallback first, then write the more-sophisticated version in an @supports rule, expecting it to override the fallback if it's supported. The performance "gotcha" here arises because @font-face rules do not override previously-defined ones for the same descriptors; instead, they accumulate.

drott commented 3 years ago

That gets a bit cumbersome in complex cases: e.g. if there are two or three color-font techologies being queried, as well as variations and a couple of shaping technologies, the @supports rule wrapping the fallback that doesn't support any of these could become pretty unwieldy.

I don't completely disagree, but I don't think combinations of shaping engine choice and other capabilities are very likely when there are barely any aat and graphite web fonts used let alone color or variable versions of those. I consider the most likely scenarios are variations yes/no, and perhaps 1-3 color technologies as a fallback ladder.

It also feels like a footgun because it differs from how @supports normally interacts with graceful degradation. With typical CSS properties, the user can write the generic fallback first, then write the more-sophisticated version in an @supports rule, expecting it to override the fallback if it's supported. The performance "gotcha" here arises because @font-face rules do not override previously-defined ones for the same descriptors; instead, they accumulate.

This "performance gotcha" only arises when you really have different glyph sets and that is a surprise to you as the author or font provider who delivers that CSS and the fallback font would be loaded inadvertently to check for glyph coverage.

For language/script subset fallback unicode-range is an established and widely used technique to control that.

For color- or variations-enhanced upgrades of a monochrome static font the glyph sets are (as you mentioned yourself) likely identical. If not, unicode-range is used to guard control fall through. In most cases, CSS and fonts are delivered from the same provider who knows the fonts' coverage. For those reasons, overall, my impression is, an accidental fall-through performance gotcha does not seem a likely footgun. I would agree with @dbaron that this seems working as intended.

A solution that avoids this accumulation issue is @supports inside @font-face which we can spec already by adding the css-conditionals-4 font-technoloy() function and allowing @supports nesting inside @font-face. Feasible for us from an implementation point of view short-term is @font-face inside @supports, nesting only later, but we are supportive of allowing and implementing that in general, it will just take more time. Would this perspective / progression be sufficient for addressing your concerns, @jfkthame ?

Another solution that avoids this accumlation issue is for example to modify the font matching algorithm based on an additional technology descriptor, or going back to some kind of technology-tagging in the src: line. I think both those avenues would lead to micro-syntaxes external to @supports.

jfkthame commented 3 years ago

This "performance gotcha" only arises when you really have different glyph sets

No, my point is the performance issue arises when the preferred and fallback fonts have the same glyph set (and precisely-enumerated unicode-range descriptors have not been used). In this case, when a character isn't supported by the preferred font, the browser will have to load the fallback as well in order to check its glyph coverage, which will be purely wasted time and bandwidth.

Nesting @supports inside @font-face would make it easier (as an author) to structure things efficiently, but I am not sure about the implementation complexity issues at this stage. We should also think about how adding nested-@supports at a later stage will work for authors who need to account for older UAs that don't support that. It'd be interesting to see an example of what the eventual CSS should look like for a page that wants to use nested @supports inside @font-face if available, falling back to @font-face inside @supports for earlier browsers.

drott commented 3 years ago

(Edited to include font matching algorithm discussion)

No, my point is the performance issue arises when the preferred and fallback fonts have the same glyph set (and precisely-enumerated unicode-range descriptors have not been used). In this case, when a character isn't supported by the preferred font, the browser will have to load the fallback as well in order to check its glyph coverage, which will be purely wasted time and bandwidth.

I don't understand. If they have the same glyph set, and same CMAP coverage - why would a character then not be supported by the preferred font? The load for the fallback only needs to be triggered if the primary font doesn't have coverage and such was determined during font analysis or shaping, but if coverage was already found, no load is needed.

  1. If the matched face is defined via @font-face rules, user agents must use the procedure below to select a single font:

If the font resource has not been loaded and the range of characters defined by the unicode-range descriptor value includes the character in question, load the font.

After downloading, if the effective character map supports the character in question, select that font.

When the matched face is a composite face, user agents must use the procedure above on each of the faces in the composite face in reverse order of @font-face rule definition.

This is the spec text from the font matching algorithm how to resolve when at the end of matching multiple fonts are in the set of web fonts, which is the case if we have an accumulated set. This does not force the UA to download both in the set, but says that the last @font-face defined (the preferred one), should be tried first.

In the case of color and variations upgrades of a conventional font with same glyph set, when would such a situation really be the case?

jfkthame commented 3 years ago

I don't understand. If they have the same glyph set, and same CMAP coverage - why would a character then not be supported by the preferred font? The load for the fallback only needs to be triggered if the primary font doesn't have coverage and such was determined during font analysis or shaping, but if coverage was already found, no load is needed.

The point is that for a character that turns out not to be supported (by either the primary or fallback fonts, as they have the same glyph set) the fallback nevertheless has to be loaded in order to determine its coverage.

So if you use the "obvious" pattern to implement progressive enhancement (or graceful degradation, to look at it from the other side):

@font-face { font-family: my-icons; src: url(my-icons-bw-fallback.woff2); }

@supports font-technology(color-COLRv0) {
  @font-face { font-family: my-icons; src: url(my-icons-flat-colors.woff2); }
}

@supports font-technology(color-COLRv1) {
  @font-face { font-family: my-icons; src: url(my-icons-gradient-colors.woff2); }
}

a browser that implements both COLRv0 and COLRv1 will see all three of the @font-face rules.

Now, when the browser encounters a character X that is not supported by my-icons, it will fail to find it in the COLRv1 resource; so it will load the COLRv0 font to check its coverage. Again, it'll fail to find the character, so it'll load the BW font; and again, fail to find the character. So it has loaded all three resources in order to check the character coverage of each, even though the author's intention was to just use the best supported version of the three.

To avoid this, the author has to construct more complex @supports rules such that any given browser will only "see" the single preferred one of the @font-face declarations, rather than all the forms it supports. Given, for example, five possible color-* technologies, this could get quite unwieldy.

LeaVerou commented 3 years ago

Do note that instead of unicode-range (which would be a pain, I agree), one could also use not in @supports instead of having a bare @font-face as the fallback.

Yes, using @supports not ... would avoid this. That gets a bit cumbersome in complex cases: e.g. if there are two or three color-font techologies being queried, as well as variations and a couple of shaping technologies, the @supports rule wrapping the fallback that doesn't support any of these could become pretty unwieldy.

One way to make this easier would be to define aliases like color-any or color-COLR (which encompasses both v0 and v1).

svgeesus commented 3 years ago

One way to make this easier would be to define aliases like color-any or color-COLR (which encompasses both v0 and v1).

Or (since we have the hyphen scheme) just color and feature; although I worry what that means when in the future we add, say, color-supercolor or features-supertype which are, naturally, not universally supported. Do they mean "supports at least one" or "supports all"?

drott commented 3 years ago

After your explanations @jfkthame , I agree that the behaviour with @supports in that sense would be different from what was in the fonts spec, where only the first, highest-capability-tagged resource of listed supported resources in the src: line would be loaded for a glyph for which there is no coverage.

As you noted, using unicode-range: for declaring the supported range does make this problem disappear altogether. In my opinion, high performance font loading strategies should and do already declare unicode-range, tools like Wakamai Fondue's beta version help in declaring it, Google Fonts does it for subsetting into script ranges. I find that an acceptable tool and established strategy for authors who care about font performance.

Also agree with @LeaVerou that catch-all aliases help with describing negative @supports rules to exclude fonts from the set.

svgeesus commented 3 years ago

By the way I notice that the specification describes in detail how to handle a src descriptor whose value is a comma-separated list with more than one list item (and most examples use that style) but is fairly silent about two other cases:

  1. There are multiple src descriptors in the same @font-face
  2. There are multiple @font-face with all the font-selecting descriptors identical

hat needs to be covered at the same level of detail.

jfkthame commented 3 years ago

As you noted, using unicode-range: for declaring the supported range does make this problem disappear altogether. In my opinion, high performance font loading strategies should and do already declare unicode-range, tools like Wakamai Fondue's beta version help in declaring it, Google Fonts does it for subsetting into script ranges. I find that an acceptable tool and established strategy for authors who care about font performance.

Yes, I'm aware of how Google Fonts (for example) uses unicode-range to split fonts into script ranges. For a major service that can invest in tooling and expertise to do this, that's clearly beneficial for performance.

I'm still a bit concerned, though, about the case of an author who is, for example, just adding a custom icon, logo or in-house decorative/branding font to a site, and hand-writing the CSS to support it; this is the kind of scenario where it's easy to imagine authors writing code along the lines of the example above, without realizing that they're causing redundant resource loads.

The CSS spec even suggests that it's reasonable to use broad-range unicode-range descriptors rather than enumerating the precise coverage of the font:

When the font is used, the effective character map is the intersection of the codepoints defined by 'unicode-range' with the font’s character map. This allows authors to define supported ranges in terms of broad ranges without worrying about the precise codepoint ranges supported by the underlying font.

So an author might quite reasonably write unicode-range: U+1f6?? for an icon font that includes a sparse subset of the entire 1F6xx block; but then if a symbol from that block not covered by the webfont is encountered, all the fallback versions will be fetched before finally resorting to the system's standard emoji font.

I think we should try to design the solution here such that authors who write their font-enrichment CSS in the "natural" way do not thereby create a hidden performance drag. Quite how best to do that isn't yet clear to me.

drott commented 3 years ago

The CSS spec even suggests that it's reasonable to use broad-range unicode-range descriptors rather than enumerating the precise coverage of the font:

I'd be in favour of changing that recommendation.

In the discussion so far, I see these constraints - am I missing something, or are there differing views?

  1. Due to implementation complexity and CSSOM implications it's harder to put @supports inside @font-face so we seem to agree on a preference to have it at the top level.
  2. If @support + a font-technology() function is placed at the top level, we may run into the cascading / accumulation issue (with varying opinions on how severe that issue is).
  3. If we define a font-technology() supports function, nothing per-se stops it from being used at the top-level.

Options we've been pondering in an internal discussion:

tabatkins commented 3 years ago

I apologize, but it's not entirely clear to me what this final concept would bring that's not already done by omitting unicode-range entirely.

drott commented 3 years ago

The way I mean it, taking Jonathan's example and adding a hypothetical fallback: no-cascade;

@font-face { font-family: my-icons; src: url(my-icons-bw-fallback.woff2); fallback: no-cascade; }

@supports font-technology(color-COLRv0) {
  @font-face { font-family: my-icons; src: url(my-icons-flat-colors.woff2); fallback: no-cascade; }
}

@supports font-technology(color-COLRv1) {
  @font-face { font-family: my-icons; src: url(my-icons-gradient-colors.woff2); fallback: no-cascade; }
}

Without fallback: no-cascade; the my-icons family would consist of three fonts that have accumulated into the my-icons font at identical attributes for weight, stretch, style. So when checking for a character that's not contained in the icon font, first my-icons COLRv1, then COLRv0, then bw have to be loaded, in that order. If there is a hyptohtetical fallback: no-cascade; descriptor, we can spec that to mean: after checking the first one (in reverse order of CSS declarations), do not look further in this cascade and do not load any others.

The way I understand it: Omitting unicode-range would usually lead to all of them being loaded and checked, until system fallback is used. Using unicode-range with tight codepoint ranges means a behavior similar to the hypothetical fallback: no-cascade;, meaning: if unicode-range indicates there's not going to be coverage, do not load this font.

jfkthame commented 3 years ago

The typical use-case here is that there are multiple resources available, each based on different font technologies, and the author wants to use the single "best" one that is supported by the UA. The alternatives should be "hidden" so that the UA doesn't waste time (and bandwidth) on them.

Doing this entirely with @supports becomes increasingly cumbersome as more technologies are considered, as each @supports block is independently defined; to ensure that exactly one of the alternatives is chosen by any given UA, the conditions have to be carefully constructed to not only check for support of a given technology, but also for non-support of any "better" technology.

It would be more natural and ergonomic for authors if this could be done by chaining the @supports blocks in an "if-elseif-elseif-else" way. Inventing some syntax here, we might have:

@supports font-technology(color-COLRv1) {
    @font-face { font-family: my-icons; src: url(my-icons-gradient-colors.woff2); }
}
@else-supports font-technology(color-SVG) {
    @font-face { font-family: my-icons; src: url(my-icons-svg.woff2); }
}
@else-supports font-technology(color-COLRv0) {
    @font-face { font-family: my-icons; src: url(my-icons-flat-colors.woff2); }
}
@else {
    @font-face { font-family: my-icons; src: url(my-icons-bw-fallback.woff2); }
}

I think a similar @else-extension to conditional rules would also be useful for @media. Is this something we could explore further?

drott commented 3 years ago

Yes, the syntax you drafted resembles very closely the proposal that @tabatkins previously published here: https://tabatkins.github.io/specs/css-when-else/ which was briefly mentioned in the notes for the last CSS WG meeting.

Yes, perhaps if we explore this further we'll have a future ergonomics improvement for @supports & font-technology(). We could define the latter now and invest in @when + @else - which might be a viable way forward.

litherum commented 3 years ago

Pursuing @else would satisfy my concerns, too. @else would have to come first, though, so we don't teach authors to do the wrong thing because the better tools aren't available yet.

If we have @else, I don't see any reason why other at-rules couldn't be inside it, too. @font-face doesn't need to be special.

My only remaining thought is general distaste for using different mechanisms to select truetype/opentype vs COLR/sbix.

svgeesus commented 3 years ago

Relevant issue for an if-elsif-else block is https://github.com/w3c/csswg-drafts/issues/112

I agree that we need a syntax where:

Note that the existing, ugly, jammed-into-format syntax already has those properties; and I don't want to see it adopted anyway just for expediency because we take too long to add an if-elsif-else construct. I also don't want us to adopt a solution "for now" that has the multiple download and fallback problems that @jfkthame has explained so well.

My only remaining thought is general distaste for using different mechanisms to select truetype/opentype vs COLR/sbix.

We will need to keep format for legacy reasons but nothing prevents our adding a format test to the new syntax along with the font technology tests. Although the spec already requires treating truetype and opentype as synonyms so format is mainly testing for new compression/deployment wrappers (woff, woff2, IFT, etc)

drott commented 3 years ago

@litherum wrote:

@else would have to come first, though, so we don't teach authors to do the wrong thing because the better tools aren't available yet.

@svgeesus wrote:

I also don't want us to adopt a solution "for now" that has the multiple download and fallback problems that @jfkthame has explained so well.

If we add an @else construct, and only after that define a font-technology() function for feature detection and @supports conditionals, we supposedly gain a form of educational advantage.

But if both are shipped in the future, whom are we preventing from still writing the less performance optimised version that @jfkthame explained where the font blobs accumulated into a family through which we need to fallback?

Aren't we overestimating this advantage of shipping a future @else before the feature detection function, given that it will still be possible to spell out the less performant version (which I still consider a niche case given that font CSS is generated in the majority of use cases)? Aren't we undererstimating the uptake of a better @else construct once it's available?

css-meeting-bot commented 3 years ago

The CSS Working Group just discussed Nesting @supports inside @font-face / font tech queries, and agreed to the following:

The full IRC log of that discussion <fantasai> Topic: Nesting @supports inside @font-face / font tech queries
<fantasai> github: https://github.com/w3c/csswg-drafts/issues/6520
<fantasai> chris: Basic problem is that we need a way to ensure that only one of the possible options works
<fantasai> chris: if you have unicode-range and a character outside that range, all the others will be loaded to see if it has that char
<fantasai> chris: so this has been paired with another issue
<fantasai> chris: It seems we need to discuss together
<fantasai> lea: Looks like primary problem with using @supports is that pattern
<fantasai> lea: of older code being unwrapped, but wrapping new code in @supports
<fantasai> lea: but that doesn't work well with @font-face
<fantasai> lea: because the second rule doesn't override the first rule
<fantasai> lea: they combine to form a single family
<fantasai> lea: although normally only second font is used
<chris> q+ to add that the existing format overload does have the "only one wins" characteristic
<fantasai> lea: if browser encounters character not in the second, it will download the first to check if it is there
<fantasai> lea: so for this we would need an else condition
<fantasai> lea: so that we never have both @font-face rules in effect at the same time
<fantasai> lea: There's a proposal from Tab to combine feature queries and media queries, and has else
<drott> q+
<fantasai> lea: Tab suspects it's easy to implement
<fantasai> lea: if this can be implemented together with font-technology(), that would be nice
<fantasai> lea: concern that if implement without it, we'll have this problematic pattern
<astearns> ack chris
<Zakim> chris, you wanted to add that the existing format overload does have the "only one wins" characteristic
<fantasai> chris: Overloading the format string does have this benefit of combining the conditionals properly
<lea> q?
<fantasai> chris: if we don't rapidly converge, we'll be stuck with that
<fantasai> astearns: So you're concerned to get if/else quickly so that practice doesn't ossify into bad syntax
<fantasai> chris: people will just ship what's in the spec now
<fantasai> myles: I thought we would remove the complicated resource grammar
<astearns> ack drott
<fantasai> drott: I spoke to implementers, to Anders and Rune who are familiar with our CSS code
<fantasai> drott: They have no immediate concerns with the when/else proposal
<fantasai> drott: Which brings my question of timing
<chris> \0/ to no concerns!
<fantasai> drott: I'm also supportive of removing the syntax in the spec now
<fantasai> drott: but eager to have something to enable font tech feature testing atm
<fantasai> drott: We're supportive of the when/else proposal, but it would be better to have font tech queries soon and maybe when/else as an upgrade path
<fantasai> astearns: Is it possible to have a font-tech syntax in the @font-face that would handle the conditional?
<fantasai> drott: Current feature in spec is encapsulated in src descriptor
<fantasai> drott: in the format() function
<fantasai> drott: Authors can order it by most advanced tech, and then the UA will pick the one that it supports
<fantasai> drott: In current proposal, without @else we have an accumulation of fonts into the family
<lea> astearns: https://drafts.csswg.org/css-fonts-4/#font-face-src-parsing
<lea> ^ that is the current syntax
<fantasai> astearns: Would it be possible to have a limited state for this font technology where you could put it into your @font-face and have a font face exist if the font technology was supported, but have it not exist if it wasn't
<fantasai> astearns: no fallback, just make this font face if the tech is supported
<fantasai> drott: You could use different families
<fantasai> lea: If you don't want fallback, that's fine. You just make an @font-face
<fantasai> astearns: so wanted to remove things from spec, remove the current syntax
<fantasai> astearns: in favor of clearer if/else
<fantasai> astearns: but people still want conditional on font
<fantasai> astearns: and it would be nice to have that font tech
<fantasai> chris: we need to do both
<fantasai> chris: for a solution
<drott> fantasai: I think we had previous notes on this, can't find it
<drott> fantasai: it was basically: we should have both, the font-technology function in @supports, and the ability to query the tech in the format function, and they should share the syntax. And the syntax should be simpler.
<astearns> s/would handle the conditional/would not handle the conditional with fallback/
<chris> q+
<drott> fantasai: for @supports, you might want to query not only if it's color, but you might want to query for format
<drott> fantasai: I would simplify the syntax of the font-technology function.
<drott> q+
<drott> fantasai: In a way to remove the sub functions, and just have a list of keywords, for example font-format-...
<fantasai> fantasai: ....
<fantasai> drott: I think you did post it somewhere, I had updated my pull request to flatten it...
<fantasai> chris: ...
<drott> q-
<lea> q?
<lea> q+
<fantasai> chris: The format shouldn't be the orphan that gets left behind that you have to do in src, it should be same conditional thing that we do in font-technology
<fantasai> chris: so if woff5 comes along, we can also put that in this new shiny syntax
<astearns> ack chris
<drott> fantasai: it should be the same function, for format and font technology
<chris> I don't really like calling it font-format
<fantasai> lea: If I understand correctly, a format should also have been a condition in @supports
<chris> yes exactly lea
<fantasai> lea: if designing today that's how we would do that
<fantasai> lea: only reason we have format function is that it's legacy
<chris> we can't get *rid* of the format legacy though, so it has to remain in the spec
<fantasai> lea: so I think what Chris is saying is that we also need to be adding a font-format() function into @supports so that authors can combine @font-technology queries
<fantasai> lea: whereas what fantasai is saying is to have only format() function, and have it allowed both in src and @supports
<fantasai> s/chris: .../lea: I think that was my proposal to flatten from color() to color-/
<fantasai> astearns: So we're looking for a way to express simper supports queries in @font-face rules
<fantasai> astearns: and remove fallback ability
<drott> fantasai: I think we're not aiming to remove fallback
<fantasai> chris: The things that drott proposed, it would be helpful to allow that as a direct query in @supports conditions
<fantasai> myles: I think adding that should be blocked on having some way of solving the problem that jfkthame described
<drott> q+
<astearns> ack lea
<fantasai> astearns: ?
<fantasai> lea: No way to do else, so authors will need to negate their queries
<fantasai> lea: and it would get very verbose and complicated
<fantasai> myles: not even sure if it's possible
<fantasai> myles: because there's a third value here, not just supported or not supported, but also case of "browser doesn't know what you're talking about"
<fantasai> chris: So need a resolution on proposal, but also how do we move forward on Tab's draft
<fantasai> chris: Can we adopt it as an ED?
<fantasai> myles: We should split this font-specific issue
<fantasai> myles: one piece blocked on else rule and one that isn't
<drott> q?
<fantasai> myles: and discuss else rule in its own CSSWG issue
<astearns> ack drott
<fantasai> drott: I discussed this issue with jfkthame offline. I think he's here?
<chris> this is its issue: https://github.com/w3c/csswg-drafts/issues/112
<fantasai> drott: In our question, jfkthame expressed some flexibility regarding timing
<fantasai> drott: I'd like to emphasize what chris was saying earlier, if we move the supports syntax from CSS as it is now, then we don't have anything to do feature testing
<fantasai> drott: I consider @supports an upgrade path
<fantasai> myles: I've heard some people say they want to remove unimplemented flexbility in the spec now, and others don't want to remove it but to reformulate to make it simpler
<fantasai> myles: either one is reasonable to me
<fantasai> lea: which part is blocked on what?
<fantasai> myles: If we want to keep the unimplemented features of the format() in src, we wouldn't need to be blocked on else
<TabAtkins> It is true that `@supports unknown-font-thing() {...} @support not (unknown-font-thing()) {...}` will fail to match both of them (the first is unknown, treated as false; the second is negated unknown, which is still unknown and thus treated as false)
<fantasai> lea: the problem with that is that we don't want microsyntaxes
<TabAtkins> whereas `@support unknown-font-thing() {...} @else {...}` would match one or the other, guaranteed.
<lea> q+
<astearns> ack lea
<fantasai> lea: Important point from the issue drott raised hasn't be raised yet
<fantasai> lea: else is syntactic sugar for negation
<fantasai> lea: but another way to work around is to use unicode-range
<fantasai> lea: drott mentioned that most font-face rules are generated, and have unicode-range alreay
<fantasai> lea: which means this isn't a problem
<fantasai> myles: unicode-range is an orthogonal feature
<TabAtkins> Oh wait, sorry, I was wrong - @supports doesn't use the unknown value.
<fantasai> myles: if author is trying to use fancy syntax that is / isn't supported
<TabAtkins> We resolved on that a bit ago.
<fantasai> myles: both @font-face rule and fallback will have the same unicode-range
<TabAtkins> Unknown things are just false in @supports.
<fantasai> myles: so the problem still applies
<fantasai> lea: Problem is if the character is not included in the range
<fantasai> myles: problem that I'm concerned about is that character is inside the unicode-range block, but not supported by the font's CMAP table
<fantasai> myles: in that case the browser will download both fonts serially
<fantasai> drott: Should have unicode-range identical to CMAP
<TabAtkins> So my statement above was wrong - both are equivalent, and you'll definitely select one or the other. (We use unknown for @media, where the browser very well *might* match an unknown query once it starts supporting it; a browser that doesn't understand a feature, by definition, doesn't support it, so that's a safe `false`.)
<drott> fantasai: Lea was concerned about multiple different microsyntaxes. My proposal doesn't do that. Format function, should have identical syntax, whether it's in src: or in @supports.
<lea> q+
<astearns> ack fantasai
<drott> fantasai: If that's the case, we can ship src: first - ship @supports version later.
<drott> q+
<astearns> ack lea
<fantasai> lea: There's another unexplored option
<fantasai> lea: what if we had an inline conditional function that does supports queries
<fantasai> lea: A supports() or supports-if() function to put inside any value
<fantasai> astearns: I think it would be a good idea to write down what you're suggesting, Lea
<fantasai> astearns: but getting a proliferation of options, unsure we can get to resolution on anything specific today
<astearns> ack drott
<fantasai> astearns: I think we can resolve at least that we would like to work on the if/else syntax
<fantasai> TabAtkins: Adopt as an ED in the WG? Currently draft in my personal repo
<lea> +1 to working on @else proposal
<jfkthame> +1
<fantasai> astearns: resolution would be to adopt, yes
<fantasai> fantasai: so that would be css-conditional-3?
<fantasai> TabAtkins: sure
<drott> q+
<astearns> ack drott
<fantasai> drott: potentially add any resolution, then idea would be to have a font-tech function to combine with that?
<TabAtkins> I also was udner the impression that Conditional started with 1.
<fantasai> dbaron[m]: I think conditional-3 is already advanced
<drott> +1 to that.
<fantasai> fantasai: oh, I meant whatever's next
<drott> sorry, fantasai, I did not capture what you said.
<fantasai> RESOLVED: Adopt if/else as next level of css-conditional
<fantasai> astearns: So question of current font-technology draft and reworking them with existence of if/else in mind
<fantasai> astearns: so take back to issue to determine what changes, if any, need to be made
<fantasai> chris: I don't see a dependency there
<fantasai> chris: I think we can adopt PR as-is
<drott> +1 as well
<fantasai> lea: +1
<fantasai> lea: this is something useful immediately
<TabAtkins> +1
<drott> zes
<fantasai> astearns: Adopting PR will resolve the issue?
<drott> s/zes/yes
<fantasai> lea: the bulk of it
<fantasai> astearns: And we can open new more tightly constrianed issues
<fantasai> astearns: So proposed resolution?
<fantasai> drott: Adds font-technology() function to @supports, which has a flat list of font technologies and options, which can be used inside an @supports rule
<drott> https://github.com/drott/csswg-drafts/commit/62cfd95a5f52604c952e4aa37be6e4d6386f88f5
<fantasai> myles: the @else rule should make it clear that it works with this new query inside @supports
<fantasai> myles: either explicitly or implicitly
<fantasai> myles: And i'd ask implementers not to implement font-technology() without @else
<fantasai> myles: because if you oonly give ability to do it wrong, people will do it wrong
<fantasai> lea: why?
<dbaron[m]> That request to implementers should be in the spec.
<fantasai> myles: because @else is the solution to this problem, so one depends on the other
<jensimmons> +1 to myles
<lea> s/lea: why?/lea: they can still do it right, it's just tedious/
<drott> fantasai: I am not sure, I agree with this particular PR.
<dbaron[m]> s/sure,/sure/
<drott> fantasai: I think the function should have identical syntax to what we should have in src:.
<drott> q+
<drott> fantasai: one question I have: font-technology - would this be allowed to be queries in src:?
<drott> s/queried/queries
<drott> s/queried/queries/
<fantasai> astearns: I think we should merge it in and take separate issues
<fantasai> chris: I edit both specs anyway
<drott> +1 to that, if we can have the font-technology PR
<fantasai> myles: but if we're making src less flexible than it is to day (in ths spec)
<astearns> ack drott
<fantasai> fantasai: happy to do so, as long as we can work on it and not just ship what's in the PR
<chris> @drott I see the PR on your fork repo but not the one on the csswg repo
<fantasai> myles: I think it's OK to resolve this, I think fantasai's idea about making them match makes sense to me
<fantasai> myles: I think making them match gives drott a path to implementing that doesn't rely on us standadizing a big new feature
<fantasai> myles: so I think that's the best path forward
<fantasai> astearns: we're not got to solve everything today
<fantasai> astearns: so let's merge the PR and file more issues
<drott> +1
<lea> +1
<chris> +1
<fantasai> astearns: any objections?
<fantasai> RESOLVED: Accept the PR
<chris> :)
<fantasai> myles: Can we add a note to the PR to say "don't implement this yet, implement this other thing first"
<fantasai> astearns: open an issue