|
| 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