Web Fonts and Providing Fallback Fonts

Web Fonts and providing fallback fonts

You are presumably using font files and a CSS file as generated by FontSquirrel. The problem with their approach is that each specific font (such as Open Sans Regular and Open Sans Bold) is represented as a separate font-family, with font weight set to normal. This means that instead of markup like <p>foo <strong>bar</strong> and simple CSS like p { font-family: Open Sans, Arial } (letting browsers default strong to bold font weight and select the suitable font from the Open Sans family), you will be forced to set fonts explicitly. This means setting both font family and font weight, implicitly with the font-family property value.

You would need to tune the CSS to get a better approach. You would use the same font family but different weights in the @font-family rule, and in the font-family rule, you would only set the family:

@font-face {
font-family: 'open_sans';
src: url('opensans-bold-webfont.eot');
src: url('opensans-bold-webfont.eot?#iefix') format('embedded-opentype'),
url('opensans-bold-webfont.woff') format('woff'),
url('opensans-bold-webfont.ttf') format('truetype'),
url('opensans-bold-webfont.svg#OpenSans') format('svg');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'open_sans';
src: url('opensans-regular-webfont.eot');
src: url('opensans-regular-webfont.eot?#iefix') format('embedded-opentype'),
url('opensans-regular-webfont.woff') format('woff'),
url('opensans-regular-webfont.ttf') format('truetype'),
url('opensans-regular-webfont.svg#OpenSans') format('svg');
font-weight: normal;
font-style: normal;
}
* { font-family: open_sans, Arial; }

And then you would just use font-weight: bold (or HTML markup that has such an effect by default, like strong, b, th, h1 through h6) for those elements that should appear in Open Sans Bold.

Doing it the way you describe appears to work on most browsers, too, but I wouldn’t count on it. Once you have declared a font as normal weight in your @font-face, setting font-weight: bold on text in that font could cause a) a failure, since a the weights don’t match or b) the font taken as a starting point for algorithmic bolding, resulting in double bolding. And if I’m not mistaken, b) is what happens on Safari (Win 7).

Is it necessary to provide a fallback font for a web font face?

I doubt you would have a problem with Google being unreachable. However some browsers do use the fallback font until the downloaded font is available.

From Google: https://developers.google.com/webfonts/faq

How is text displayed while the browser is still loading the font
file?

Browser behavior varies depending on the type of browser. Some will only display the text after the font file is loaded, others will
use the fallback font from the font stack and then refresh the page
when the font is available. The latter behavior is generally referred
to as the "flash of unstyled text." For browser details, see the
Technical Considerations page.

For greater control over how browsers behave while the font is still loading, use the WebFont Loader.

Multiple webfonts + Fallback

A solution called font linking is to use the same font-family name multiple times on @font-face declarations and set font-variant and font-weight to the corresponding value, so for example in plain css:

@font-face {
font-family: 'charter';
src: url('font/charter_bold_italic-webfont.eot');
src: url('font/charter_bold_italic-webfont.eot?#iefix') format('embedded-opentype'),
url('font/charter_bold_italic-webfont.woff') format('woff');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'charter';
src: url('font/charter_bold-webfont.eot');
src: url('font/charter_bold-webfont.eot?#iefix') format('embedded-opentype'),
url('font/charter_bold-webfont.woff') format('woff');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'charter';
src: url('font/charter_italic-webfont.eot');
src: url('font/charter_italic-webfont.eot?#iefix') format('embedded-opentype'),
url('font/charter_italic-webfont.woff') format('woff');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'charter';
src: url('font/charter_regular-webfont.eot');
src: url('font/charter_regular-webfont.eot?#iefix') format('embedded-opentype'),
url('font/charter_regular-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}

Now you can use like any other font without worrying about faux bold or italic, with support for <strong> <b> <i> and <em> tags and with fallback font which correctly displays weights and styles.

If you want to read more: SmashingMagazine - Setting Weights And Styles With The @font-face Declaration

Prevent browsers from using default/fallback fonts

You can intercept the font substitution process by throwing in a catchall font, using some equivalent of font-family: userChoice, yourCatchAll where yourCatchAll is a font that has a generic glyph for all characters.

The problem is in finding such a font. The LastResort font distributed by the Unicode Consortium would be ideal, since it also visually indicates the category of the character in broad terms, but its EULA does not seem to allow modifications. It is debatable whether this applies to the construction of web font formats (like .eot and .woff).

The Unicode BMP Fallback Font appears to have more liberal rules of use, but it displays a character simply as its Unicode number in a box (and supports only Basic Multilingual Plane, though it contains all characters that most people ever heard of).

Adding fallback fonts to the @font-face definition

No, you cannot specify any fallback fonts inside a @font-face rule, because such a rule defines a font face and assigns a name to it. Inside the rule, the font-family part can contain only one name, the name you choose to assign. It would be pointless list several names there, since only the first one can possibly matter (and, besides, in this context no name has any predefined meaning, e.g. Arial would not mean the Arial font but be just an arbitrary assigned name).

Fallback fonts can be specified only in normal font-family rules.

Consider organizing your style sheet so that the relevant font-family list appears only once, using a suitable list of selectors, like

p, blockquote, .foobar, .something {
font-family: MyWebFont, Arial, Helvetica, sans-serif;
}

How do web browsers implement font fallback?

Font fallback in browsers (as opposed to, say, in an OS) is based on two things:

  1. The CSS specification, which gives the fonts that are to be used for fallback, and
  2. The text engine, which does text shaping.

The CSS spec is fairly trivial in this respect, simply giving the list of fonts using their system names, but several possible "catch all" fonts that are in no way guaranteed to be the same from computer to computer (there is no reason to assume that serif maps to Times or Times New Roman, for instance).

The fallback algorithm used by text engines is entirely up to the engine, but usually kicks in during the glyph lookup step: the text engine sees a string of code points, and tries to use a font to shape that string. For each point in the sequence, it checks whether the font has a matching glyph (by consulting the CMAP table and subtables), or a rule that tells the engine that there may be a glyph to use only if more code points follow, through the GSUB mechanism (For instance, a font without glyphs for the individual letters e, t and c, but with a glyph for & and a GSUB rule that says the sequence e+t+c should be in-text replaced with the single glyph &), and when it's finished accumulating this kind of "unit of points", it shapes the text and hands it back to whatever asked it to shape text.

If, during glyph lookup, it turns out the font doesn't contain anything that lets the engine shape a particular code point (i.e. running through the CMAP data as well as the GSUB rules still shows "there is no glyph") then the text engine can do two things:

  1. Give up. There is no glyph, instead use the .notdef outline defined as glyph id 0, and generally give you text with lovely empty boxes (lovingly called "tofu" by font folks) or question marks.
  2. Attempt font fallback, where it will try another font to find a glyph for the unsupported code point in.

When using fallback, an engine can go down a list of alternative fonts until either: (a) a glyph is found, or (b) the list is exhausted, at which point the engine has to give up, and will use the .notdef glyph. Whether the engine grabs the .notdef glyph from the original font, or from the last font in the list, is entirely up to the engine (although usually it'll go with the first font, for legibility)

There is no "standard" algorithm for this defined anywhere; font fallback is basically a convenience mechanism offered by text engine authors, like how browsers come with bookmark managers (handy, and not part of any spec). As far as OpenType is concerned, there are no requirements on whether an engine should just serve up .notdef when a glyph is not found, or whether it should serve up the part it could shape, then find the missing glyph somewhere else, and render text that way. CSS implies that your text engine should have at least some form of font fallback, but it doesn't specify how it should work, or when it should kick in.

CSS: Fallback fonts

you can specify multiple fonts:

p {
font-family: "Times New Roman", Times, serif;
}

The browser will try the first one, if that one isn't available the second, and so forth. In the end it uses the family serif, so the browser chooses any serif font. You should use the monospace family.

So in your case, something like this is what you want:

p {
font-family: "Lucida Console", "Courier New", monospace;
}

Webfont as Fallback for local font

Unfortunately this isn't how CSS works. In order to implement the webfont you'd first need to include it in your website (via HTML <link>, CSS @import or through JavaScript).

This means that prior to your font-family declaration, the font will have already been loaded (and presumably counted as a view by the company who hosts the font).

One solution could be to detect whether the browser is able to load the Calibri font by default (using JavaScript), and if not then download the webfont and use that instead, but in doing this you'd create a strage user experience whereby the page would default to using a font that could be loaded and then after a short while change to the webfont (after JavaScript has loaded it and your CSS has kicked in).

If you are willing to go down that path, there are several topics about how to detect which font has been loaded through JavaScript, such as Detecting which font was used in a web page



Related Topics



Leave a reply



Submit