w3c / csswg-drafts

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

[css-fonts-4] @font-face font-variant cannot easily be reverted to default #2265

Open faceless2 opened 6 years ago

faceless2 commented 6 years ago

Lets say I have this in my stylesheet

@font-face {
    font-family: "Bickham";
    src: url(bickham.ttf);
    font-variant: historical-forms;
}

If I ever wanted to use the "Bickham" font without the historical forms - i.e. the default rendering of the font, with no features applied - I can't do this without resorting to font-feature-settings: "hist" 0;

This seems like an oversight, particularly so if you're trying to encourage people to use the font-variant-X properties instead of font-feature-settings. More generally, having a rule set in a stylesheet that cannot easily be overriden in a later stylesheet is just not very CSS.

Intuitively you might specify font-variant: none in the element's style, but "none" is only an option with font-variant-ligatures, where it works as expected. Adding a "none" option to font-variant-numeric, font-variant-alternates etc. that explicitly turns off any previously set features would be the obvious option - however this would imply changing the behaviour of font-variant: none.

So might be an idea to add a new keyword like "reset" to the various font-variant-X properties (and font-variant). Or, perhaps, slightly redefine the initial value for these properties to also reset any values set in the @font-face rule. So our solution could look like this:

@font-face {
    font-family: "Bickham";
    src: url(bickham.ttf);
    font-variant: historical-forms;
}

.nonhistoric {
   font-variant: initial; /* implied font-variant-alternates: initial */
}

Or is this behaviour intentional?

svgeesus commented 6 years ago

You have a point. The specific example you give is fairly easy:

.nonhistoric {
  font-variant-alternates: none;
}

Because the spec defines

normal None of the features listed below are enabled.

But consider instead the following

section {
  font-variant-alternates: swash(flowing) annotation(circled) historical-forms;
}
section .nonhistoric {
  // leave the swash and the annotation settings but unset historical forms
}

One solution would be to add off switches, for example no-historical-forms and swash(none) and so on.

faceless2 commented 6 years ago

In fact you can turn off swashes, stylesets etc with no change to the current spec by setting the value to 0

@font-feature-value { @swash { none : 0 } }
.noswash { font-variant-alternates: swash(none); }

It might be nice to assign "none" a special value without needing a font-feature-value, but it's not necessary. However the problem remains with historical-forms, tabular-nums etc., and I agree with your reasoning behind for a proposed "no-" options for those.

But I'm not sure I follow your point with font-variant-alternates: none - you quoted the definition of "normal": did you mean "normal" instead of "none"? Because, if I've understood the specification correctly, normal doesn't turn off font-variant-alternates: it just doesn't turn them on (a distinction I missed on the first pass of our implementation).

Both interpretations are effectively identical except when one of the rules is defined in the @font-face rule. So for example:

@font-face {
    font-family: myfont;
    font-variant: historical-forms;  /* turn on "hist" for all instances of "myfont" */
}
body {
    font-family: myfont;
    font-variant-alternates: normal;  /* don't enable any new features. The features set in @font-face still apply as described in the font-feature resolution rules */
}

Or were you proposing a new "none" keyword for font-variant-alternates and friends? The problem with this is that it slightly changes existing behaviour of the shortcut property font-variant: none. Current situation:

@font-face {
    font-family: myfont;
    font-variant: historical-forms;
}
body {
    font-variant: none;
    /* implies:
     * font-variant-ligatures: none;      explicitly turns off common-ligatures;
     * font-variant-alternates: normal;   don't enable any new features; historical-forms still applies as in above example
    */
}

Proposed situation:

@font-face {
    font-family: myfont;
    font-variant: historical-forms;
}
body {
    font-variant: none;
    /* implies:
     * font-variant-ligatures: none;    explicitly turns off common-ligatures;
     * font-variant-alternates: none;   explicitly turns off historical-forms
    */
}

I don't know if this actually matters or not, but I'm slightly more wary of changing existing behaviour of an existing keyword than I would be about adding a new keyword.

Finally, I've created a pull request (hopefully; still getting my head around git) for two new testcases for this behaviour, as I could find none. They build on your tests Chris, I've put an explanation of the logic in the comments which hopefully will help make sense of them (or alternatively, highlight where I've misunderstood the specification). Pull request is https://github.com/w3c/web-platform-tests/pull/9397

faceless2 commented 6 years ago

On re-reading this I need to follow myself up. First, I'm aware you probably wrote the spec Chris so I'm wincing slightly as it looks like I'm trying to correct your interpretation of it :-) Not my intention, sorry if it came across that way.

Second, from testing here it looks like "font-variant" in a @font-face rule is only supported by webkit currently, with the existing implementation slightly buggy anyway. So any change of behaviour by adding a new "none" keyword to the various font-variant features is, practically, irrelevant.

svgeesus commented 6 years ago

Finally, I've created a pull request (hopefully; still getting my head around git) for two new testcases for this behaviour, as I could find none. They build on your tests Chris, I've put an explanation of the logic in the comments which hopefully will help make sense of them (or alternatively, highlight where I've misunderstood the specification). Pull request is w3c/web-platform-tests#9397

Thanks for doing that. Creating tests for that section was on my 'get around to it' pile for a while. I just reviewed and approved the tests.

I think that normal and none are distinct and would merit separate keywords (sorry my attempt to explain that was less than clear). normal is typical CSS auto-like "do whatever you normally do" while none really is "switch everything off".

litherum commented 6 years ago

I wish we had additive CSS....

svgeesus commented 6 years ago

@faceless2 Many thanks for the test cases for the font-variant precedence rules. These are now in the WPT test suite and the results are part of the implementation report. Fonts 3 is now nearing completion, we have only 10 out of 475 tests not passed by two implementations.

For syntax changes (adding none or no- keywords), given the stability of the rest of Fonts 3, we prefer to defer this to Fonts 4 (which is actively being worked on). Please confirm that this is ok for you?

faceless2 commented 6 years ago

@svgeesus that's fantastic news, the testcases are spectacularly useful for us so we're just glad to be able to contribute. Of course to the deferral of new keywords to css-fonts-4, getting a line under css-fonts-3 is the most important.

svgeesus commented 5 years ago

(Removing the deferred, satisfied, and fonts-3 tags s this becomes a more clearly open fonts-4 issue)