Font
a typeface in a file the page downloads
What it is
A font, called a webfont when a site serves it and a font face in the CSS specifications, is the file holding the drawn letters of one design in one weight and style, along with the tables that tell software which drawing stands for which character and how to space them.
Typographers keep the design and its files apart. Ubuntu is a typeface; Ubuntu
Light and Ubuntu Bold Italic are fonts of it. CSS keeps the same split. A font
family groups faces under one name, and each @font-face rule describes a
single face: the family it joins, where to fetch it, the weight and style it
covers, the characters it can draw and what to show while it loads.
@font-face {
font-family: "Reading Serif";
src:
local("Reading Serif Regular"),
local("ReadingSerif-Regular"),
url("/fonts/reading-serif-400.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: "Reading Serif", Georgia, serif;
}
The font-family property on an element is a list read from left to right. The
specification chooses a family and a face for each character in a run of text,
taking the first face that matches the requested weight and style and contains a
glyph for that character. One line can therefore be set in two fonts when the
first lacks a letter, and the generic name at the end of the list, serif,
sans-serif, monospace or system-ui, means some installed font always takes
the remainder.
On the web the file is almost always WOFF2: the same OpenType or TrueType
outlines and tables, repackaged for transfer and compressed with Brotli. Inside,
the cmap table maps each character code to a glyph, and other tables carry the
numbers a layout engine needs, such as ascent, descent, line gap and where an
underline sits and how thick it is. Those numbers decide line height and spacing
as much as the letterforms decide the look.
Why it matters
Every weight and style is a separate download. A design using regular, italic
and bold puts three files between a reader and the text set in them, and each
one adds bytes to the first visit. The unicode-range descriptor lets a family
be split into pieces by script, and the specification forbids a browser from
downloading a piece for characters outside its range, so a page fetches only the
pieces its text uses.
Text in a webfont cannot be drawn before the file arrives, so the browser needs
a policy for the wait. The font-display descriptor sets it. With block, the
specification recommends a block period of 3s, during which the text is laid out
but drawn invisibly. With swap, the block period is 100 ms or less, the
fallback font appears almost at once, and the webfont replaces it whenever it
lands. With fallback, the swap window is short, with 3s recommended, after
which the page keeps the fallback. With auto, the browser decides, and many
treat it like block.
Where the file lives matters too. Font requests use CORS, so a font on another origin loads only when that server allows it, and every request to another company’s server tells it the reader’s address and which site they are on. Serving fonts from the site’s own host removes both the extra connection and the observer.
A font is software under a licence. The SIL Open Font License allows use, study, modification and redistribution as long as the fonts are not sold by themselves, and bars a modified version from using a reserved font name without permission. A font bought for print may carry different terms for the web, so read the licence before the file goes on a server.
Coverage is the last concern. A font draws only the characters its cmap lists.
Most of the Cyrillic alphabet sits in the run U+0400–045F, but the Ukrainian
letter ґ lives at U+0490–0491, so a subset or a range written for Russian text
leaves it to whatever fallback comes next.
What it looks like in practice
The site’s credits page lists what reaches a reader’s browser as five things, and three of them are webfonts. Ubuntu, by Dalton Maag for Canonical, is under the Ubuntu Font Licence. Ubuntu Mono, the same family’s fixed-width cut, sets the code. Shantell Sans, based on the artist Shantell Martin’s felt-marker handwriting, is under the SIL Open Font License and writes the margin notes. All three come from the site’s own machine, and the page says why: a webfont from someone else’s CDN is a third party watching you read. Ubuntu Mono and Shantell Sans load only on the pages that carry code or a margin note.
Splitting one typeface by script is what the Safari underline note is about. The site serves Ubuntu in six pieces, three weights of Latin and three of Cyrillic, each declaring the characters it covers, so English and Danish pages fetch three Latin files and no Cyrillic ones, and Ukrainian pages the reverse. All six shared one family name, and in Safari a face with a non-Latin range degrades skip-ink, the gap an underline leaves around a descender, for every character in its family, Latin text included. Deleting the three Cyrillic declarations at runtime took the measured gaps from 1.8/1.0/1.0px to 4.5/11.0/5.0px. The fix gave the Cyrillic faces a family name of their own and put it in the stack after Ubuntu: three renamed declarations and one stack entry, with Chrome untouched and Ukrainian still set in Ubuntu at identical widths. The same note shows how much a font’s own numbers vary: Ubuntu declares an underline thickness of 0.056em for Light, 0.020em for Medium and 0.120em for Bold.
The landing page in front of the company’s own git forge had been a hand-maintained copy of the main site’s design, and every difference found between the two was an accident rather than a decision. Two of the five were about fonts: a font declaration that collapsed two weights to one on any machine with the family installed, and a weight used with no font shipped for it. None of the five was visible in a screenshot. The copy was deleted, and the landing page is now built by the main site’s own templates.
Where it goes wrong
- Text stays invisible while the file loads. Under
block, and often underauto, a slow connection shows a laid-out page with no words in it for up to the block period. Useswapfor body text and preload the one or two files the first screen needs. A font preload needs thecrossoriginattribute even for a same-origin file, because the preload has to match the CORS request it stands in for. - The page jumps when the font arrives. A fallback with different widths and
line heights breaks lines in other places, and the swap reflows them. The
specification advises fallbacks whose metrics closely match the webfont. Where
none does, a
local()face for the fallback withascent-override,descent-overrideandline-gap-overridebrings its vertical metrics into line, so the swap changes letterforms rather than layout. - Bold and italic nobody drew. When a family has no bold face, the browser
may thicken the regular one, and it may slant the regular one when there is no
italic. Strokes smear and roman letters lean. Ship every face the design uses,
or set
font-synthesistononeso a missing face shows up in review as upright, regular-weight text rather than a fake. local()takes a face, not a family. The name insidelocal()matches a single face by its full name or its PostScript name. Writing the family name there for every weight can match one installed face for all of them, so bold renders as regular on exactly the machines that have the family installed. Name each face, both ways, or leavelocal()out.- A missing glyph mixes typefaces. A face that lacks a character hands it to the next family, so one word can show two designs. A subset cut too tightly does the same for a whole script. Check coverage against the text the site actually publishes, in every language it publishes.
Further reading
- CSS Fonts Module Level 4 —
@font-face, the matching algorithm,unicode-range,font-displayand the synthesis controls. - WOFF File Format 2.0 — how OpenType and TrueType fonts are packaged and compressed for the web.
- OpenType cmap table — the table that decides which characters a font can draw.
- SIL Open Font License — the licence itself, with its conditions on copies, modified versions and reserved names.
- WebKit bug 255159 — the Safari report on underline skip-ink behind the site’s note.