1

I have a single page static site where I have configured the appcache to cache all resources needed to load the page for future use, in order to minimize server requests and make the page available offline.

I have run into a problem with font support. I use web fonts with @font-face and woff, ttf, svg, and eot formats to ensure compatibility with all browsers. The issue is that I have to include multiple fonts in the cache manifest in order to ensure cross-browser compatability. While normally a browser would just read the @font-face ,select the appropriate font format, and download only that format (or none at all if it's available locally), I could not find a way to accomplish that with appcache while ensuring that everything is available cached and offline. My solution was just to include all of the font formats in the cache manifest. While this worked, it was extremely wasteful, because clients downloaded fonts they didn't need.

Eventually I did some research on browser support, comparing appcache, ttf, woff, eot, and svg fonts. I came to the conclusion that all browsers that support appcache work with either woff or ttf, and that svg and eot have very little support. (The limiting factors are that android has no woff support and IE has no ttf support). Using this, fonts still displayed correctly everywhere. However, it's still really inefficient, as two fonts are downloaded regardless of need.

So, in summary, what is the recommended way to deal with fonts and appcache most efficiently?

JC Hulce
  • 1,551
  • 2
  • 13
  • 23
  • Here are the links to the individual font format browser support pages (I can't link them due to my new user restrictions): http://caniuse.com/woff http://caniuse.com/ttf http://caniuse.com/svg-fonts http://caniuse.com/eot – JC Hulce Jul 15 '13 at 22:29

2 Answers2

1

I don't believe you need to explicitly list the font in your appcache manifest. So long as the font is used on the page it should get automatically included in the browser's application cache.

idbehold
  • 16,833
  • 5
  • 47
  • 74
  • Huh, I just tested that with chrome and it works perfectly. I thought that having a cache manifest on a page would only cache the html. Does this behavior work with anything else (css, js, etc)? – JC Hulce Jul 15 '13 at 23:10
  • Yes, it should work with everything I believe. The other thing you could do is setup your manifest file to be handled by server-side code (e.g. appcache.manifest.php) and then dynamically include the font files you need cached based on the user-agent string. It's not ideal but it will work. – idbehold Jul 16 '13 at 00:16
  • And, it didn't work. My earlier result was a fluke because that system had the font available locally so it just used that. Other systems didn't load the font at all. I then included a "NETWORK: *" section in my cache manifest. Now it worked everywhere, but it didn't cache. Once I disconnected the network the font would fail. – JC Hulce Jul 16 '13 at 00:18
  • My application is delivered over a cdn that doesn't allow me to do things dynamically based on the client. I was thinking about some javascript feature detection but cache manifests can't be loaded with javascript apparently. So I guess I'll use IE conditional statements to use different manifests (ttf for every browser except IE) – JC Hulce Jul 16 '13 at 00:24
1

As I have since discovered in another question, IE 9+ DOES support TTF fonts, as long as they are formatted correctly. This means that all major browsers that support the HTML5 Application Cache can also work with ttf fonts, so I only need to include that one format in the cache. I have tweaked the bulletproof @font-face syntax to prefer TTF over WOFF (since that's what will be in the cache) and added wildcards to my cache manifest to deal with any edge cases.

Here's my modified @font-face format:

@font-face {font-family: '<font-family>';src: url('<font-file>.eot?#iefix') format('embedded-opentype');src: local('<font-family>'),url('<font-file>.ttf')  format('truetype'),url('<font-file>.woff') format('woff'),url('<font-file>') format('svg');}

Here's the cache manifest format:

CACHE MANIFEST
<other stuff>
...
/<font-file>.ttf

NETWORK:
*.ttf
*.woff
*.svg
*.eot

Note: as brought up in the comments below, using wildcards in the NETWORK section of a cache manifest might not be valid markup. Using the absolute URL is a better way to go.

And here's a webpagetest result of IE10 using and caching the TTF font. I have verified that the @font-face still seems "bulletproof" across browsers.

There are two minor issues with this setup:

  • Clients that already have the font available locally will still download it (this isn't a major issue for me, as only about 5% of visitors have it)
  • Edge cases: browsers that will read the manifest but won't work with ttf for whatever reason will still work online, but not offline. I could not find a browser that exhibits this behavior, but anything is possible. Again, only a very small percentage of clients will experience it.
Community
  • 1
  • 1
JC Hulce
  • 1,551
  • 2
  • 13
  • 23
  • Also, the reason why I don't just put a general network asterisk in the manifest is that not having it can prevent some XSS attacks by not allowing external scripts/resources/connections that I don't explicitly let through. – JC Hulce Jul 17 '13 at 23:18
  • Does the `*.ext` work? I thought you were only allowed to use `*` by itself. – idbehold Jul 18 '13 at 00:05
  • Yup, it works for me. Wildcards in the network and fallback sections are yet another thing where support is unclear. Here's a source that says yes: http://keyholesoftware.com/2012/09/17/html5-offline-capabilities-using-the-cache-manifest/ And here's one that says no: http://html5doctor.com/go-offline-with-application-cache/ But in any case absolute URLs can still be used and that's probably what I should have done – JC Hulce Jul 18 '13 at 03:23