Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are CSS-inlined (base64-encoded) webfonts rendered with a delay?

Twitter started using a WOFF webfont (screenshot). This font is base64-encoded and inlined in a CSS file which is <link>ed inside the <head>.

Now, if I understand correctly, <link>ed CSS style sheets are render-blocking, i.e. browsers will not render the page until they've fetched/parsed its external CSS files.

In this case, when visiting Twitter, the browser should load the CSS file containing the webfont and then render the page with that webfont. However, I've performed a test (on empty cache/browser history) in Chrome/Windows, and the webfont is displayed with a delay: The text on the page is first rendered using the default sans-serif font of the OS, and then, after a few seconds, the webfont "kicks in" and replaces the system font.

See here: https://www.youtube.com/watch?v=yt9UXHmNofA (the switch happens at the 6 sec mark)

Why is this happening? Why is Chrome not displaying the webfont on the first render? Could it be that the base64 decoding happens asynchronously?

like image 866
Šime Vidas Avatar asked Jun 03 '14 23:06

Šime Vidas


1 Answers

(putting this together into an answer so people don't have to read through the endless comments)

Unexpectedly, this is unrelated to the browser, rather it is about how Twitter includes the style sheet.

Basically, a cookie named "goth" determines whether the font style sheet is injected in a blocking or non-blocking way.

In-depth explanation

In the first load (without cookies) of a Twitter page, the font style sheet is asynchronously injected (that is, in a non-blocking way) and a cookie named "goth" is set¹.

In subsequent requests which send the goth cookie, the font style sheet is served in a blocking way, in the form of a <link rel="stylesheet"> in the <head> of the document.

To see this by yourself, follow these simple instructions:

  • In Chrome, open view-source:https://twitter.com/simevidas

  • Open the DevTools (F12) -> "Resources" tab -> Cookies -> twitter.com, delete the goth cookie.

  • Hit reload (F5). As your request headers did not include a goth cookie, the font style sheet (gotham-narrow-v3.css) is not present in the document's head, rather it is in a hidden HTML-encoded JSON string (pic). It will be injected asynchronously via JavaScript later.

  • Check your cookies in the DevTools Resources tab again -- just reloading the view-source page was enough to set the goth cookie again for me, but in case you don't have the goth cookie just open a Twitter page.

  • Now with the goth cookie set, reload the view-source page again. You will notice that the font style sheet (gotham-narrow-v3.css) is now included via a <link rel="stylesheet"> inside the document's head (pic). This one is loaded before the first render, as <link>ed CSS style sheets are render-blocking.

And of course, hard-refreshing (Ctrl/Cmd+F5) will still send the cookies and load the font style sheet in the blocking manner.


¹: Initially, I believed this was supposed to be some sort of lazy loading with feature detection, but I've tested it on Firefox 3.5 (which does not support WOFF webfonts) and Firefox 3.0.13 (which does not support webfonts at all) and both are having the goth cookie being set.

As the cookie is actually a session cookie (is discarded once the browser is closed), it is more plausible that the first asynchronous-injection is done to speed up the first render, and subsequent requests assume that the font style sheet is already cached and inserts it in a blocking way to prevent flash-of-unwebfont'ed-content (a more specific form of FOUC which I just made up).

I haven't made it through the minified JS to be sure of that, but feel free to edit this answer or comment if you manage to.


And yes, this is highly localized topic which probably won't help many people, I've just decided to put it all together in a clear and concise answer just so those who are interested in this topic don't have to venture into the endless comments in the question.

like image 188
Fabrício Matté Avatar answered Sep 20 '22 06:09

Fabrício Matté