Search code examples
htmlfontscorspreload

Why do we need the "crossorigin" attribute when preloading font files?


To correctly preload font files, we're told we always need the crossorigin attribute applied to our <link rel="preload" /> tags, e.g:

<link rel="preload" href="fonts/comicsans.woff2" as="font" type="font/woff2" crossorigin>

Can anybody give me the true reason for this? All I can find are links in MDN that just dictate this requirement, without going into any detail as to why:

https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#cors-enabled_fetches

When preloading resources that are fetched with CORS enabled (e.g. fetch(), XMLHttpRequest or fonts), special care needs to be taken to setting the crossorigin attribute on your element. The attribute needs to be set to match the resource's CORS and credentials mode, even when the fetch is not cross-origin.

As mentioned above, one interesting case where this applies is font files. Because of various reasons, these have to be fetched using anonymous-mode CORS (see Font fetching requirements).

It seems counterintuitive to my understanding of CORS, and why it's necessary. I'm sure there's a good reason for this, I just can't find it.

Before anybody just links to the same docs I'm talking about, see below:

https://drafts.csswg.org/css-fonts/#font-fetching-requirements

I'd really like an in depth answer from somebody who really knows why this is a requirement, and what it's purpose is, with some evidence (docs, etc) to back it up.


Solution

  • The HTML attribute crossorigin defines how to handle crossorigin requests. Setting the crossorigin attribute (equivalent to crossorigin="anonymous") will switch the request to a CORS request using the same-origin policy. It is required on the rel="preload" as font requests require same-origin policy.

    The same-origin policy is required on almost all new resource types, such as fetch(), <script type="module"> or fonts. It doesn't apply to legacy resource types (images, scripts, css, video, audio) because of backwards-compatibility issues. <link rel="preload"> is a special case because it is a modern feature which needs to support legacy resource types, such as preloading an image.

    the ideal is, from now on, you always SOR by default when you introduce a new type of linking. It's just the right thing to do, because it lets us avoid having to care about a whole annoying class of security issues. Source

    This requirement was then added to the W3C draft for CSS fonts.

    For font loads, user agents must use the potentially CORS-enabled fetch method defined by the [FETCH] specification for URL's defined within @font-face rules. When fetching, user agents must use "Anonymous" mode, set the referrer source to the stylesheet's URL and set the origin to the URL of the containing document. Source

    I have also come across repeated comments that it was requested by the font foundries to prevent font piracy, but I cannot substantiate that with evidence.

    Other related links: