Skip to content

Commit 1916ce6

Browse files
committed
[css-fonts-4] Explainer for src descriptor supports
1 parent e74d0a5 commit 1916ce6

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

css-fonts-4/src-explainer.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# The @font-face src descriptor
2+
3+
## Introduction
4+
5+
The @font-face rule is used
6+
to automatically download Web Fonts on demand,
7+
and use them for rendering
8+
without the user having to install them.
9+
The fonts are discarded after use,
10+
and do not become installed fonts.
11+
12+
The src descriptor contains the url of the font to be downloaded, plus additional metadata so that unsuitable or unusable fonts are not wastefully downloaded.
13+
14+
Other descriptors include the font family name,
15+
the range of font weights supported,
16+
the range of Unicode characters supported by the font,
17+
and so on.
18+
These are used for matching styling requests (properties)
19+
to available Web Fonts.
20+
21+
For example,
22+
23+
@font-face {
24+
font-family: "Foo";
25+
src: url(https://example.org/Foo.baz);
26+
}
27+
h1 {
28+
font-family: "Foo", serif;
29+
}
30+
31+
32+
## History of @font-face
33+
34+
Originally [introduced in 1997](https://www.w3.org/TR/WD-font-970721)
35+
and then [merged into CSS2](https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#referencing),
36+
@font-face was implemented as far back as
37+
Internet Explorer 3 (with the EOT font format).
38+
39+
Although consensus was reached on the CSS syntax,
40+
there was no consensus on the font format to use.
41+
Embedded OpenType (from Microsoft and AGFA),
42+
Truedoc Portable Font Resource (from Bitstream and Netscape),
43+
and SVG Fonts (W3C)
44+
were all used by early implementations.
45+
It was therefore necessary for the src descriptor to indicate
46+
the font format, in addition to the url.
47+
48+
At the time there were no MIME types for fonts,
49+
and significant resistance at IETF and IANA to adding a font top-level type.
50+
51+
> I initially planned to use MIME types there, but given significant resistance to the idea of a font/* top level type we went with the 'format' string as a temporary workaround. Temporary meaning two decades or so. [source](https://github.com/w3c/csswg-drafts/issues/633#issuecomment-340527309)
52+
53+
Relying on filename extensions would also have been fragile,
54+
so the original proposal used string-based
55+
[format hints](https://www.w3.org/TR/WD-font-970721#src).
56+
57+
@font-face {
58+
font-family: "Foo";
59+
src: url(https://example.org/Foo.pfr) format("truedoc-pfr");
60+
}
61+
62+
Lack of a common format crippled interoperability
63+
and resulted in minimal uptake of this feature.
64+
When development of CSS 2.1 began in 2002,
65+
@font-face (and its associated descriptors)
66+
were dropped from the specification.
67+
68+
In 2010, the [FPWD of WOFF 1.0](https://www.w3.org/TR/2010/WD-WOFF-20100727/)
69+
heralded convergence on a Web font format,
70+
and @font-face was re-introduced with
71+
[CSS Fonts 3 in 2011](https://www.w3.org/TR/2011/WD-css3-fonts-20111004/).
72+
73+
By 2018, when CSS Fonts 3
74+
[became a Recommendation](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/),
75+
support for [@font-face with a src descriptor](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#src-desc)
76+
and a defined set of format strings was universal
77+
in Web browsers and in CSS to PDF converters.
78+
79+
In parallel, WOFF 1.0 was being smoothly replaced by
80+
[WOFF 2.0](https://www.w3.org/TR/2021/REC-WOFF2-20210706/),
81+
fallback being provided by multiple urls and format hints
82+
in the src descriptor:
83+
84+
/* load WOFF 2.0 font if possible, otherwise use WOFF 1.0 font */
85+
@font-face {
86+
font-family: something;
87+
src: url(example.woff2) format("woff2"),
88+
url(example.woff) format("woff");
89+
}
90+
91+
Useage of WebFonts has taken off,
92+
from near-zero in 2011
93+
to 80% of all web sites in 2020.
94+
95+
[!Growth in Web Font usage](https://www.w3.org/TR/2020/NOTE-PFE-evaluation-20201015/images/2020-07-22_Web_Font_Usage.png)
96+
97+
This success has enabled the use of fonts on the web
98+
to be further refined and improved,
99+
but also poses a significant long-tail Web-compatibility issue
100+
if an changes are made to this src descriptor.
101+
102+
_Further historical background may be found in the
103+
introductory sections of the
104+
[Progressive Font Enrichment Evaluation Report](https://www.w3.org/TR/2020/NOTE-PFE-evaluation-20201015/)_
105+
106+
## History of font technologies
107+
108+
Early fonts contained raster bitmaps at various sizes.
109+
These were soon improved by adding vector outlines of the glyphs,
110+
although sadly with multiple, competing, non-interoperable technologies.
111+
PostScript™ Type 1 outlines, from Adobe,
112+
were soon joined by TrueType™ outlines, from Apple
113+
(to say nothing of less sucessful vector outlines such as Speedo or Intellifont).
114+
115+
The typographic and layout capabilities of fonts were also improved,
116+
with TrueType GX and AApple Advanced Typography from Apple,
117+
OpenType from Microsoft,
118+
and Graphite from SIL.
119+
At first, these were used in print
120+
and in native applications,
121+
but the Web lagged behind in typographic richness.
122+
123+
CSS Fonts 3
124+
[opened up these font features to CSS](https://www.w3.org/TR/css-fonts-3/#font-rend-props),
125+
primarily focussing on OpenType.
126+
That specification sadly notes the limitation of the format hint
127+
in ensuring a downloaded font has the desired features:
128+
129+
> Given the overlap in common usage between TrueType and OpenType [OPENTYPE], the format hints "truetype" and "opentype" must be considered as synonymous; a format hint of "opentype" does not imply that the font contains Postscript CFF style glyph data or that it contains OpenType layout information
130+
131+
Font formats continued to evolve;
132+
OpenType 1.7 added
133+
[color font support](https://docs.microsoft.com/en-us/typography/opentype/otspec170/)
134+
although sadly, as implementation largely preceeded standardization,
135+
there were four different ways
136+
each largely tied to a single vendor, OS, or browser.
137+
OpenType 1.8, with rather more coordination, added
138+
[font variations](https://docs.microsoft.com/en-us/typography/opentype/otspec180/)
139+
which was rapidly adopted at both the OS and browser level.
140+
141+
The [FPWD of CSS Fonts 4](https://www.w3.org/TR/2017/WD-css-fonts-4-20170711/)
142+
in 2017
143+
continued to refine font features
144+
and added support for [variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props)
145+
and [color fonts](https://www.w3.org/TR/css-fonts-4/#color-font-support).
146+
It was becoming clear however,
147+
that the format hint was insufficient by itself
148+
and that combinatorial explosion would result
149+
(formats such as "opentype-variation" were briefly specified,
150+
but "opentype-variation-SVG-Graphite" would become
151+
unweildy and error-prone).
152+
153+
## Use cases
154+
155+
1. I want to use color fonts,
156+
but browser A supports only color font format X,
157+
while browser B supports color font format Y
158+
in older versions
159+
and both X and Y in newer versions.
160+
However, color fonts are large,
161+
so putting both X and Y in one font increases download size unacceptably.
162+
All fonts are in "opentype" format,
163+
so the font format by itself cannot be used to make the choice.
164+
165+
[!Please work](https://www.w3.org/TR/css-fonts-4/images/please.png)
166+
167+
2. A minority language is best supported by Graphite features,
168+
but Graphite is only implemented in Firefox.
169+
For Chrome and Safari, I want to fall back to OpenType features.
170+
Both fonts are in "opentype" format,
171+
so again the font format by itself cannot be used to make the choice.
172+
173+
## Design constraints & alternative solutions
174+
175+
The largest constraint is that older browsers must continue
176+
to sucessfully parse the src descriptor,
177+
and to end up ignoring links to fonts containg unsupported features,
178+
while following the desired link to the fallback.
179+
180+
This was discussed in 2016, in Issue 663 [@font-family src: should accept a specifier which lists font requirements](https://github.com/w3c/csswg-drafts/issues/633)
181+
and again in 2018, in Issue 2540 [Content authors want to modify style based on the presence of color fonts](https://github.com/w3c/csswg-drafts/issues/2540)
182+
183+
There were various proposals, such as an additional "features" function using OpenType table names:
184+
185+
@font-face {
186+
font-family: heading-font;
187+
src: url(fancy-font.woff2) format("woff2") features("CPAL,FVAR"),
188+
url(fallback-font.woff2) format("woff2"),
189+
url(fallback-fallback-font.woff) format("woff"),
190+
url(how-old-is-your-browser-font.ttf) format("ttf");
191+
}
192+
193+
but that was unacceptable because of backwards compatibiity
194+
(older browsers would drop the _entire_ src descriptor,
195+
not just the first element in the comma-separated list),
196+
and also a desire to avoid microsyntaxes which:
197+
198+
> wreak havoc on object models [source](https://github.com/w3c/csswg-drafts/issues/633#issuecomment-372928475)
199+
200+
Thus, it was [resolved](https://github.com/w3c/csswg-drafts/issues/633#issuecomment-380469287)] in 2018 to put the extra "supports" requirements inside the parentheses of the format hint, but without string concatenation.
201+
202+
There was also Issue 6340 [Drop bracket matching step from @font-face src: line parsing](https://github.com/w3c/csswg-drafts/issues/6340), resolved in June 2021,
203+
about whether to do parenthesis matching before splitting the value of the src descriptor on commas.
204+
205+
The use cases mentioned above are then solved
206+
using [the current syntax](https://drafts.csswg.org/css-fonts-4/#src-desc)
207+
as follows:
208+
209+
/* 1. prefer COLRv1, then SVG-in-OpenType, then COLRv0 */
210+
@font-face {
211+
font-family: jewel;
212+
src: url(jewel-v1.woff2) format("woff2" supports COLRv1),
213+
url(jewel-svg.woff2) format("woff2" supports SVG),
214+
url(jewel-v0.woff2) format("woff2" supports COLRv0),
215+
url(boring.ttf) format("woff2");
216+
}
217+
218+
/* 2. prefer Graphite over OpenType layout, if supported */
219+
@font-face {
220+
font-family: rare;
221+
src: url(rare-graphite.otf) format("opentype" supports features(graphite)),
222+
url(rare.otf) format("opentype" supports features(opentype)),
223+
url(fallback.ttf) format("truetype");
224+
}
225+
226+
The original format hints were strings, although limited to a defined set.
227+
In CSS Fonts 4, either strings or keywords may be used for the format.
228+
The new font technology specifiers are keywords.
229+
There is an open Issue 6328 [@font-face src: url() format() keywords vs. strings ambiguous in spec](https://github.com/w3c/csswg-drafts/issues/6328) regarding how to serialize this.
230+
231+
An alternative solution to putting supports inside format is proposed in Issue 6520 [Nesting of @supports inside @font-face](https://github.com/w3c/csswg-drafts/issues/6520).

0 commit comments

Comments
 (0)