htmlfontsfont-facekmpkeyman-developer

Why are my external fonts not loading in an .htm file?


I'm trying to make documentation for a mobile keyboard for toki pona, and I'm going to be sharing the file around in a Keyman keyboard package. For one reason or another, files in the package can't be picked up by the HTML file, and the package can't be unzipped very easily (I hate Keyman), so the file looks like a bunch of .notdef to whoever reads it that has the keyboard installed.

I tried putting CSS into the file, but I can't get ANY external site to show up with the font properly. I may have just not tried hard enough, but my CSS should have worked.

<head>
<style>
  @font-face {
    font-family: 'nn';
    src: url(https://github.com/etbcor/nasin-nanpa/raw/refs/heads/main/versions/nasin-nanpa-5.0.0-beta.2-UCSUR.otf) format("opentype");
  }
  .sp {font-family: 'nn', sans-serif;}
</style>
</head>
<p class="sp">foo 󱥬󱤀</p>

My problem is, it works perfectly fine with a completely different font from a different keyboard!

<head>
<style>
  @font-face {
    font-family: "ff";
    src: url(https://www.kreativekorp.com/lib/font/FairfaxHD.ttf) format("truetype");
  }
  .sp {font-family: 'ff', sans-serif;}
</style>
</head>
<p class="sp">foo 󱥬󱤀</p>

This wouldn't be an issue if I didn't use the other font for the keyboard already, and considering it's documentation for a keyboard based on radicals, I'd kind of want the user to know which key is which in a specific keystring.

As a hobbyist with minimal knowledge of HTML or CSS, I am completely stuck here.


Solution

  • Github repositories are not intended to work as cdns.
    Fonts are in particular strict when it comes to cross-origin-access.

    Create cdn link with correct CORS header

    However you can easily create a publicly available link with a suitable CORS header using a cdn like jsdelvr.

    1. navigate to the repository directory and open the desired file
    2. copy the current URL - e.g https://github.com/etbcor/nasin-nanpa/blob/refs/heads/main/versions/nasin-nanpa-5.0.0-beta.2-UCSUR.otf
    3. for jsdelvr links you can use their free link generator tool https://www.jsdelivr.com/github

    @font-face {
      font-family: "nn";
      src: url(https://cdn.jsdelivr.net/gh/etbcor/nasin-nanpa@refs/heads/main/versions/nasin-nanpa-5.0.0-beta.2-UCSUR.otf)
        format("opentype");
      font-weight:400;
      font-style:normal;
    }
    
    body {
      font-family: "nn";
      font-size:10vw;
    }
    <p class="nn"> 󱤀   󱤁  󱤂  󱤃  󱤄  󱤅  󱤆  󱤇  󱤈  󱤉  󱤊  󱤋  󱤌  󱤍  󱤎  󱤏</p>

    Alternative: create base64 data URL

    You may also embed the font completely - provided the ultimate application supports data urls. In the below example I created a base64 data URL using transfonter online converter.

    @font-face {
      font-family: "nn";
        src: url('data:font/ttf;charset=utf-8;base64,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') format('truetype');
        font-weight: normal;
        font-style: normal;
    }
    
    
    .nn {
      font-family: "nn";
    }
    <p class="nn"> 󱤀   󱤁  󱤂  󱤃  󱤄  󱤅  󱤆  󱤇  󱤈  󱤉  󱤊  󱤋  󱤌  󱤍  󱤎  󱤏</p>

    See also "Converting and rendering web fonts to base64 - keep original look"