edison23

Zápisky šíleného jazykového editora

CSS: Webfonts in an HTML web page on localhost

How to circumvent the same origin policy when you need to load local fonts using CSS on your localhost machine

Datum: 2019-08-16
Kategorie: Guides EN
Štítky: CSS HTML base64

Obsah


I have created a tool named TOCjs in as webpage for generating table of contents by parsing an HTML document user provides. The tool was designed to work locally hosted so neither the user needs a webserver to use the tool, nor I need a webserver to make the tool available for users.


Little bit of self-advertisement: if you’d like to download TOCjs, proceed to the GitHub repository here. If you’d like to use it online, I host it for that purpuse on my server here, too. Please be aware the online version might be a few commits behind the Git repository if I forget to pull it on the server.


Problem

I wanted the interface of the tool to look good so I’ve downloaded a webfont, saved it next to my CSS stylesheet and linked the fontname.ttf in the @font-family{}. I believe it worked at first a few months ago but recently I’ve noticed the webfont loads fine on my webserver but my Firefox throws an error in the console when I load it locally on my computer:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///S:/tools/tocjs/assets/Nunito-Light.ttf. (Reason: CORS request not http).

The issue here was that the browser expects CSS to make HTTP calls which it obviously does on a server, but on local it’s not an HTTP call because the local computer doesn’t have a webserver. Thus, the browser throws an error about the same origin policy being violated. I’ve googled around on how to solve it to no avail so I’ve logged a question to StackOverflow and soon got pretty straightforward answer. The answer also pointed me to another answer on SO which I thought was not really relevant to me at the Googling time (turns out it was).

Solution

Convert the font to a string in base64 encoding and insert it into the CSS. It’ll make the CSS file data size at least the same as the font file data size is, but the browser won’t have to worry about the cross-origin requests when the page is loaded locally.

I’ve used OpinionatedGeek’s Base64 Encoder to convert the font file and then I’ve created a separate CSS file named e.g. font-definition-base64.css defining my @font-family like this:

@font-face {  
   font-family: 'My Font Name';  
   font-style: normal;  
   font-weight: 400;  
   font-display: swap;  
   src: url(data:font/ttf;base64,THE-ENCODED-FONT-STRING) format('truetype');  
}

Then, in my main CSS file, I’ve added a call to the beginning to load the font-definition-base64.css file:

@import url('font-my-font-name-base64.css')

After this, the browser loads my font family perfectly well even if the HTML file is loaded in a browser on a local PC.