Using @font-face with an SVG font embedded in the current HTML page

I have a standalone HTML document I want to distribute, without any external dependencies. I'm using a non-standard font in this document that only some of my users will have installed.

For those users that do not have the font installed, I am including a copy of the font in an embedded SVG document at the top of the <body>. (I'm using a one-glyph font for this example, the real document is using a complete font.)

<svg style="display: none;"><defs>
  <font id="MyFontElement">
    <font-face font-family="MyFont" />
    <glyph unicode="A" horiz-adv-x="950" d="M0,0L0,100L100,100L100,200L0,200L0,300L100,300L100,400L200,400L200,500L300,500L300,600L400,600L600,600L600,500L700,500L700,400L800,400L800,300L900,300L900,200L800,200L800,100L900,100L900,0L600,0L600,100L700,100L700,200L800,200L800,300L100,300L100,200L200,200L200,100L300,100L300,0L0,0M300,400L600,400L600,500L300,500L300,400Z" />    
  </font>
</defs></svg>

SVG fonts do not look as nice as ordinary fonts, so I only want the SVG font to be used if the font is not installed locally. If the font was defined in an external SVG document, I could use it at a lower priority than the locally-installed font like this: (fiddle)

<style>
  @font-face {
    font-family: "My Font";
    src: local("My Font"), url("fonts.svg#MyFontElement") format("svg");
  }
</style>
<p style="font: 3em 'My Font';">
    Alphabet
</p>

screenshot

Unfortunately, none of the obvious variations seem to work for a font in the current document: (fiddle)

  src: local("My Font"),
       url("./#MyFontElement") format("svg"),
       url("./#MyFontElement"),
       url("#MyFontElement") format("svg"),
       url("#MyFontElement");

Even without a @font-face declaration, the font is already available in the document as MyFont, the font-family specified in the <font-face />. However, this will be used at a higher priority than a native font named MyFont, so it is not an solution.

I hoped that I might be able to refer to it as local("MyFont")... (fiddle)

  src: local("My Font"), /* local */
       local("MyFont"); /* embedded */

...but that doesn't work either.

I could give the embedded font a different name and use it at a lower priority, style="font-family: LocalFont, EmbeddedFont", but I'm allowing users to import snippets from local files into the document and those local files will refer to the font only by the standard name. It would be possible to rewrite these references when they're imported, but I don't like that solution.

How do I refer to an SVG font embedded in the current document from a @font-face declaration?

Upvotes: 7

Views: 18728

Answers (2)

Andy Davies
Andy Davies

Reputation: 5824

Convert the font to a data URI and embedded it in the CSS declaration: (fiddle)

<style>
@font-face {
  font-family: "My Font";
  src: url("data:application/octet-stream;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCIgPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+CiAgPGZvbnQgaWQ9Ik15Rm9udEVsZW1lbnQiPgogICAgPGZvbnQtZmFjZSBmb250LWZhbWlseT0iTXlGb250IiAvPgogICAgPGdseXBoIHVuaWNvZGU9IkEiIGhvcml6LWFkdi14PSI5NTAiIGQ9Ik0wLDBMMCwxMDBMMTAwLDEwMEwxMDAsMjAwTDAsMjAwTDAsMzAwTDEwMCwzMDBMMTAwLDQwMEwyMDAsNDAwTDIwMCw1MDBMMzAwLDUwMEwzMDAsNjAwTDQwMCw2MDBMNjAwLDYwMEw2MDAsNTAwTDcwMCw1MDBMNzAwLDQwMEw4MDAsNDAwTDgwMCwzMDBMOTAwLDMwMEw5MDAsMjAwTDgwMCwyMDBMODAwLDEwMEw5MDAsMTAwTDkwMCwwTDYwMCwwTDYwMCwxMDBMNzAwLDEwMEw3MDAsMjAwTDgwMCwyMDBMODAwLDMwMEwxMDAsMzAwTDEwMCwyMDBMMjAwLDIwMEwyMDAsMTAwTDMwMCwxMDBMMzAwLDBMMCwwTTMwMCw0MDBMNjAwLDQwMEw2MDAsNTAwTDMwMCw1MDBMMzAwLDQwMFoiIC8+ICAgIAogIDwvZm9udD4KPC9kZWZzPjwvc3ZnPgo=") format("svg");
}
</style>
<p style="font: 3em 'My Font';">
    Alphabet
</p>

There's one caveat: you can't use an ID specifier (#MyFont) with a data URI like this. Therefore you can only have a single font in the encoded file, rather than having multiple and referring to them individually. (Not that you'd want to; duplicating the data for multiple embedded fonts in the declaration for each font would be a huge waste of space.)

Upvotes: 5

gilly3
gilly3

Reputation: 91497

Specify the local font name first in the css, then the embedded font name:

p {
    font-family: MyFontLocalName, MyFontEmbeddedName;
}

http://jsfiddle.net/gilly3/xX6Bv/5/

If the MyFontLocalName is installed on the user's computer, that font will be used, otherwise MyFontEmbeddedName will be used.

Upvotes: 1

Related Questions