Saturday, August 8, 2009

The Font Matching Process

Font Matching is the process that a browser employs to find the font to be used to render an (X)HTML element. Usually, the process is straightforward, but becomes complicated when the font-family does not have a font for bold or italic or small caps (or for any combination of these), or if it does not contain the glyphs necessary to render the text.

Web browsers maintain a database of all the fonts that are available to a web page — operating system fonts, @font-face fonts and the browser's internal fonts (if any).

The Font Matching Process

  1. All the properties of the font that is required to display the element are determined.
  2. The value of the font-family property of the text will be the name of the first font family with which a match will be attempted.
  3. font-style is handled in this step:
    1. If the element's text does not have the property oblique or italic, the currently selected font is retained and the browser goes to step 4.
    2. If the element's text has the property oblique or italic, and the the font family contains an oblique or italic font, the font is chosen and then the browser goes to step 4.
    3. If the element's text has the property oblique or italic, and the font family does not contain an oblique or italic font, the normal font is slanted to simulate oblique/italic text and then the browser goes to step 4.
  4. font-variant is handled in this step:
    1. If the element's text does not have the property small-caps, the currently selected font is retained and the browser goes to step 5.
    2. If the element's text has the property small-caps, then the browser looks for a small caps version of the currently selected font. For example, if the currently selected font is Arial Italic, the browser looks for Arial Italic Small Caps. This leaves two possibilities:
      1. The font family does not contain a small caps version of the currently selected font — the browser then simulates small caps by down scaling capital letters of the currently selected font. The browser then goes to step 5.
      2. The font family contains a small caps version of the currently selected font — the browser then selects the small caps version of the currently selected font. The browser then goes to step 5.
  5. In this step, font-weight is checked:
    1. If the element's text has the font weight property set to normal, the currently selected font is retained and the browser goes to step 6.
    2. If the element's text has the font weight property set to anything other than normal, the browser looks for a matching weight in the font family. For example, if font-weight: 100; or if font-weight: bold;, the browser looks for a font in the font family of weight 100 or 700, respectively. Therefore, there are two possibilities:
      1. The element's text has the font weight set to lighter than normal ( 100,200, or 300) or 500:
        1. If the font family contains a version of the currently selected font of the required weight, the font is selected and the browser goes to step 6.
        2. If the font family does not contain a version of the currently selected font of the required weight, the browser chooses the normal version of the currently selected font and goes to step 6.
      2. The element's text has the font weight set to bold or 600, 700, 800 or 900:
        1. If the font family contains a version of the currently selected font of the required weight, the font is selected and the browser goes to step 6.
        2. If the font family does not contain a version of the currently selected font of the required weight, and if the font-family contains a bold version of the currently selected font, the browser chooses the bold version of the currently selected font and goes to step 6.
        3. If the font family does not contain a version of the currently selected font of the required weight, and if the font-family does not contains a bold version of the currently selected font, the browser simulates boldface by increasing the stroke width of the currently selected font and goes to step 6.
  6. In this step, the selected font is scaled to the required font size.
Note 1: If the element contains a glyph that is not found in the first font family, the browser chooses the next specified font family (if any) or the browser's default fallback font. The browser then goes through the entire font matching process for that glyph only. However, Internet Explorer 6 does not follow this process, it displays an empty "box" character when a glyph is not available.

For example, if Comic Sans MS does not contain a particular mathematical symbol, then, to display that symbol only, the browser will use the next specified font in the CSS declaration that does contain the symbol (say Times New Roman). Therefore, Comic Sans MS will be used for all the element's text except for the mathematical symbol, which will use Times New Roman.

Wednesday, August 5, 2009

The @font-face at-rule

The @font-face rule can be used for a number of things:

  1. Fonts that are not commonly provided by operating systems can be used on a webpage. The font files are downloaded by the browser when the page is loaded.
  2. Can be used to give simpler names to operating system fonts
  3. Operating system font-family names can be re-assigned to downloadable font files.
  4. Multiple font locations can be specified. Therefore, if a particular font is not provided by the viewer's operating system, only then will the browser download the font from the server.
  5. Complete font-families containing a boldface font, an oblique/italic font, and multiple weights can be created using @font-face.
  6. Special downoladable fonts such as light or oblique/italic can be specified for operating system font-families.
General Syntax

The general syntax of an @font-face rule is:
@font-face { descriptor: value }
Here is an example of an @font-face rule:
font-face {
font-family: Example;
src: url(http://www.example.com/example.ttf)
}

In the example, font-family and src are descriptors and Example and url(http:/www.example.com/example.ttf) are values. The descriptor, the colon and the value together are called font-descriptors.

The font-family Descriptor

Every @font-face rule must have the font-family descriptor. The font-family descriptor's value specifies the name of the font family for which the subsequent font descriptions apply. The value of font-family can also be the name of an operating system font family, in which case the font description will override the default properties of the font family.

Here is an example of the font-family descriptor:

font-family: "Example Modern";

The src Descriptor

The src descriptor indicates the location of the font file associated with the font family name and, optionally, a format hint of the font file. The location of the file can be indicated by a URL or, if the font is provided by the operating system, by the font family name. ; An @font-face rule can have only one src font-descriptor.

In an @font-face rule, the value of the src font descriptor can be a comma separated list of sources. If the font file cannot be found at the first location, the browser will try the second location.

Here is an example of the src font descriptor with only one location specified:
@font-face {
font-family: "Example Modern";
src: url(http://www.example.com/example.ttf) format("truetype")
}

The src descriptor can also point to a "local" font. A local font is the name of a font that is provided by the operating system.

Here is another example with two locations specified:
@font-face {
font-family: "Example 1";
src: local("Example 1"), url(http://www.example.com/example_1.otf)
}


Format Hints

The format hint consists of the word format followed by the font file format name in quotes, inside parentheses. The whole expression appears at the end of a url location in the src font-descriptor.
The format hint will tell the browser what format the font file specified in url is. Based on that information, the browser can avoid downloading unsupported font files.

Here is a table of currently defined format hints:

Format Hint Font Format File extensions
"truetype" TrueType .ttf
"opentype" OpenType .ttf, .otf
"truetype-aat" TrueType with Apple Advanced Typography extensions .ttf
"embedded-opentype" Embedded OpenType .eot
"svg" SVG Font .svg, .svgz

The format hints "truetype" and "opentype" are considered equivalent to each other.


Embedded OpenType (eot)

Internet Explorer 6, 7 and 8 only support embedding of fonts in Microsoft's Embedded OpenType (eot) format. Eot files are not supported by other browsers. Eot files can be created from font files that have the ttf extension. Therefore, eot files can be created only from TrueType font files and OpenType TT font files, not OpenType PS (.otf) files. The open source application fontforge can be used to convert otf fonts to ttf in order to convert them to eot.

Eot files are compressed and also allow restricted access — a root url is specified when creating the eot file and the browser will only load the eot file from html pages that are below the specified root url. An eot file can either contain all the glyphs contained in a font file or only the glyphs that were selected at the time of creation of the eot file (subsetting).

Eot files can be created using Microsoft's Web Embedding Fonts Tool (WEFT) or the open-source ttf2eot. While ttf2eot is much easier to use than WEFT, it can only convert a ttf file to eot — it does not support subsetting and domain restriction.

Here is an example of the CSS code to embed an eot font file:
@font-face {
font-family: "A Yummy Apology";
src: url(http://www.example.com/yummy.eot);
}

font-style with @font-face

The font-style descriptor can be used to specify the oblique or italic fonts of a font-family. All major browsers consider oblique and italic as equivalent. Therefore, it is not currently possible to specify both an oblique and an italic font in a font-family.

Here is an example of how @font-face can be used to specify both a normal and oblique/italic font for a downloadable font-family:
@font-face {
font-family: "Example 1";
src: url(http://www.example.com/example_reg.ttf) format("truetype");
}
@font-face {
font-family: "Example 1";
src: url(http://www.example.com/example_italic.ttf) format("truetype);
font-style: italic;
}

font-weight with @font-face

The font-weight descriptor can be used to specify fonts for different font weights of a font-family.

Example 1:
@font-face {
font-family: "Example 2";
src: url(http://www.example.com/example2_reg.ttf) format("truetype");
}
@font-face {
font-family: "Example 2";
src: url(http://www.example.com/example2_bld.ttf) format ("truetype");
font-weight: bold;
}

Example 2:
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_reg.ttf) format("truetype");
}
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_lig.ttf) format("truetype");
font-weight: 100;
}
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_med.ttf) format("truetype");
font-weight: 200;
}

font-stretch with @font-face

The font-stretch descriptor can be used to specify the fonts to be used for different font widths within a font-family. However, the font-stretch property is currently not supported by any major browser.

Example:
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_reg.ttf) format("truetype");
}
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_cond.ttf) format("truetype");
font-stretch: condensed;
}
@font-face {
font-family: "Example";
src: url(http://www.example.com/example_expa.ttf) format("truetype");
font-stretch: expanded;
}

Browser Support

Firefox 3 and Opera 9.6

Firefox 3 and Opera 9.6 do not support @font-face. They completely ignore it.

Firefox 3.5, Safari 3.2.3 and Safari 4

Firefox 3.5, Safari 3.2.3 and Safari 4 fully support @font-face. However, there are some small differences between them in terms of feature implementation.
Firefox 3.5 only allows relative links in url specifications. Therefore, by default, the font files cannot be in another domain. This restriction can be relaxed using HTTP Access Controls. No other major browser implements such a restriction.
Safari 3.2.3 does not support number font-weights.
If a normal font is specified in an @font-face rule containing font-weight: bold or a font-weight of 600, 700, 800 or 900, Safari 3.2.3 and Safari 4 simulate bold face when rendering the text that the font is applied to. Firefox 3.5 does not.
Similarly, Safari 3.2.3 and Safari 4 simulate slanted text when using a normal font specifed by an @font-face rule for slanted/oblique text. However, Firefox 3.5 does not.
Eot files are not supported by any of these browsers.

Chrome 2

Chrome 2 partially supports @font-face — it does not support downloading of font files but supports all the features of @font-face with operating system (local) fonts.
If a normal font is specified in an @font-face rule containing font-weight: bold or a font-weight of 600, 700, 800 or 900, Chrome 2 simulates bold face when rendering the text that the font is applied to. Similarly, Chrome 2 also simulates slanted text when using a normal font specifed by an @font-face rule for slanted/oblique text.
Eot files are not supported by Chrome 2.

Internet Explorer 6, Internet Explorer 7 and Internet Explorer 8

Internet Explorer 6, Internet Explorer 7 and Internet Explorer 8 have basic support of @font-face with eot files. They do not support ttf and otf files. They only support simple @font-face rules that download eot files. They ignore the following:

  • @font-face rules that have format hints
  • @font-face rules with more than one location
  • @font-face with font-stretch

Firefox 3.5, Safari 3.2.3, Safari 4, Chrome 2, Internet Explorer 6, Internet Explorer 7 and Internet Explorer 8 do not support font-stretch in @font-face rules.

Tips

Internet Explorer 6, Internet Explorer 7 and Internet Explorer 8 download ttf and otf fonts specified in @font-face rules even though they do not support them. To prevent this, always use format hints when specifing ttf and otf fonts in @font-face rules.


When using a downloadable font in a web page, to ensure that both users of Internet Explorer and other browsers get to see the text in the correct font, one should have both a ttf/otf file and an eot file.

The @font-face rule for the eot file should appear before the @font-face rule for the ttf/otf file. This ensures that the appropriate file is loaded in Internet Explorer and other browsers.

Example:
@font-face{
font-family: example;
src: url(yummy.eot)
}
@font-face{
font-family: example;
src: url(yummy.ttf) format("truetype");
}


Both Microsoft's Web Embedding Fonts Tool (WEFT) and the open-source ttf2eot can only convert ttf fonts to eot. Therefore, it is necessary to first convert otf fonts to ttf in order to convert them to eot. The open source application fontforge can be used for this purpose.


The official w3.org specification of @font-face can be found here.