Open hamishwillee opened 2 years ago
CC @svgeesus: this sounds like a useful clarification and it's something that I discussed recently with @jfkthame.
My assumption is that multple
src
descriptors are allowed if valid.
This would prevent setting/updating src
via CSSOM, assuming such use case exists and that the specs explicitly support this and define what should happen.
I guess browser implementations register font source definitions when parsing src
therefore multiple declarations are already accepted and none is ignored.
The author can already define multiple sources with comma-separated values:
src: url("FallbackURLForBrowsersWhichDontSupportIncrementalLoading.woff2") format("woff2"),
url("MyIncrementallyLoadedWebFont.otf") format(opentype) tech(incremental);
The
src
descriptor value must be parsed according to section CSS Syntax 3 § 5.3.11 Parse a comma-separated list of component values.
I guess browser implementations register font source definitions when parsing
src
therefore multiple declarations are already accepted and none is ignored.
No, as far as I am aware browsers keep only the last (valid) src
descriptor they see. E.g. in Chrome:
> s = document.createElement("style"); document.body.appendChild(s);
> s.textContent = "@font-face { font-family: x; src: url(x.ttf); src: url(y.ttf); }";
> document.styleSheets[document.styleSheets.length-1].cssRules[0].cssText
< '@font-face { font-family: x; src: url("y.ttf"); }' // only the second src descriptor is present
But:
> s.textContent = "@font-face { font-family: x; src: url(x.ttf); src: url(y.ttf) format(foo); }";
> document.styleSheets[document.styleSheets.length-1].cssRules[0].cssText
< '@font-face { font-family: x; src: url("x.ttf"); }' // second src was invalid, so the first is retained
Regarding fallbacks:
The author can already define multiple sources with comma-separated values:
src: url("FallbackURLForBrowsersWhichDontSupportIncrementalLoading.woff2") format("woff2"), url("MyIncrementallyLoadedWebFont.otf") format(opentype) tech(incremental);
With this, any browser that accepts WOFF2 would use the first source, and so the incremental option would never be considered.
To have the intended effect, this should be the other way around:
src: url("MyIncrementallyLoadedWebFont.otf") format(opentype) tech(incremental),
url("FallbackURLForBrowsersWhichDontSupportIncrementalLoading.woff2") format("woff2");
This would be the "preferred" or modern way to express fallbacks. However, there are existing browsers that do not recognize the tech()
function and will drop the entire src
descriptor (not just that item from the list -- contrary to what the spec says). (They'll similarly drop the entire descriptor if any one item has some other kind of syntax error.)
Therefore, for maximum compatibility it's advisable to use multiple src
descriptors, with the "modern" full descriptor last, but preceded by a simpler, backward-compatible fallback for browsers that will reject the modern version. So we end up with something like:
@font-face {
font-family: MyFamily;
src: url("FallbackURLForBrowsersWhichDiscardModernSrcDescriptors.ttf");
src: url("MyIncrementallyLoadedWebFont.otf") format(opentype) tech(incremental),
url("FallbackURLForBrowsersWhichDontSupportIncrementalLoading.woff2") format("woff2");
}
Legacy browsers that reject the second src
entirely will keep the first version of the descriptor; modern browsers will override the first src
with the second, and use the first supported resource from its list.
However, there are existing browsers that do not recognize the tech() function and will drop the entire src descriptor (not just that item from the list -- contrary to what the spec says). (They'll similarly drop the entire descriptor if any one item has some other kind of syntax error.)
Thanks @jfkthame . Just FYI, I did some playing and it is more like "most" than "some". FF109 is first version that drops just invalid item from list. Chrome 108 is the first version that will drop just a tech()
descriptor but will drop all descriptors if you were to put in fred()
say (i.e. it seems to allow just the tech()
case, even if not supported).
CSS Fonts Module Level 4, Editor’s Draft, 15 September 2022
Says in
@font-face
rule:Then example 22 shows where we have multiple src descriptors, allowing fallback:
My assumption is that multple
src
descriptors are allowed if valid. If so perhaps the initial sentence could reflect this. Not sure how - maybe something like