Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom font not displaying in SVG pattern used as background-image

I'm working with an SVG pattern that uses a custom font, so as to use that pattern as a background image on an HTML page.

Everything renders fine in Chrome and Safari but it starts to get funny in Firefox:

  • Firefox renders the SVG along with the custom font text just fine when I open the SVG file itself (so far so good!);
  • However, Firefox does NOT render the custom font anymore when that same SVG file is used as the background to an HTML element (!)

I've spent hours trying to isolate the issue and a fresh pair of eyes would be welcome.

Here's what I've got in short:

CSS:

@import url(http://fonts.googleapis.com/css?family=Indie+Flower);

body {
    background: url(pattern-google.svg);
}

SVG file:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" height="200" width="200">
    <style type="text/css">@import url(http://fonts.googleapis.com/css?family=Indie+Flower);</style>
    <defs>
        <!-- Geometry -->
        <g>
            <rect id="square" x="0" y="0" width="200" height="200" />
        </g>

        <!-- Patterns with Text -->
        <pattern id="pattern" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse" text-anchor="middle" font-size="20" font-family="Indie Flower, sans-serif" style="font-family: Indie Flower, sans-serif;">
            <rect x="00" y="00" width="40" height="40" fill="transparent" />
            <text x="00" y="00" fill="#777">S</text>
            <text x="40" y="00" fill="#777">S</text>
            <text x="20" y="20" fill="#777">S</text>
            <text x="00" y="40" fill="#777">S</text>
            <text x="40" y="40" fill="#777">S</text>
        </pattern>
    </defs>

    <!-- Graphics -->
    <use xlink:href="#square" transform="translate(0, 0)" fill="url(#pattern)"/>
</svg>

The HTML itself does not really matter but I've linked it below. I did not produce a jsfiddle in the end because I could not host the SVG file there.

(Outside of the demo, the real-world application here is that I want to use a custom font to display phonetic symbols. (As background image, to help people learn them.) Doing so in SVG saves me the hassle to export to bitmap anytime I make a change in design.)

like image 359
Fabien Snauwaert Avatar asked Jul 16 '14 18:07

Fabien Snauwaert


People also ask

Can I use SVG as background image?

SVG images can be used as background-image in CSS as well, just like PNG, JPG, or GIF. All the same awesomeness of SVG comes along for the ride, like flexibility while retaining sharpness. Plus you can do anything a raster graphic can do, like repeat.

Why does my font change when I save as SVG?

The reason is simple. Font is displayed incorrectly because it is not installed in your operating system's fonts library. Consequently, the computer simply replaces the font with any other available choice.

Do SVG files embed fonts?

Nano scans SVG automatically and inserts only the fonts that are used. For example, if bold is not used or if no text exists, then no fonts will be embedded.


1 Answers

You are using SVG in an image context. I.e. either via the html <img> tag, the SVG <image> tag or in your case as a background image.

In Firefox (and likely in other UAs at some point) images must consist of a single file only. Any data external to the image file (pattern-google.svg) is ignored. If you display the SVG directly then external data is loaded/used.

So what can you do...

Load the data as a data URI. I.e. base64 encode http://fonts.googleapis.com/css?family=Indie+Flower but read the final paragraph before you do this and then stick that data directly in the svg file itself.

So the import would look like this...

@import url('data:text/css;base64,whatever the base 64 encoded data looks like...')

Do be careful though because http://fonts.googleapis.com/css?family=Indie+Flower itself has external data so that data itself must itself be encoded as a data URI. I.e. you must go all the way down the rabbit hole. And change that file as I've sketched out below.

@font-face {
  font-family: 'Indie Flower';
  font-style: normal;
  font-weight: 400;
  src: local('Indie Flower'), local('IndieFlower'), url(**convert this file to a data URI too before you convert the whole file to a data URI**) format('woff');
}

Once you've done that you can then encode the whole file as a data URI and @import it.

So, to reiterate step by step...

  1. Convert http://themes.googleusercontent.com/static/fonts/indieflower/v5/10JVD_humAd5zP2yrFqw6nhCUOGz7vYGh680lGh-uXM.woff to a data URI
  2. Replace http://fonts.googleapis.com/css?family=Indie+Flower with a version that has the data URI from step 1
  3. Convert the file in step 2 to a data URI
  4. @import the data URI from step 3

There are plenty of sites online that will create data URIs.

like image 81
Robert Longson Avatar answered Sep 22 '22 16:09

Robert Longson