Fonts / What happens to the text afterwards
Small caps, oldstyle figures and other OpenType features in a PDF
Optional glyph substitutions built into a font, which are the difference between real small capitals and shrunken capitals, and which are off unless asked for.
What is actually going on
A well-made font carries alternate glyphs: true small capitals drawn at the right weight, figures designed to sit in running text, discretionary ligatures, alternate letterforms. None of them are used by default. What people reach for instead is the crude approximation the browser will do for free, and the two are not the same: font-variant-caps asking for real small capitals uses glyphs the designer drew, while scaling capitals down produces letters that are too light for the text around them because stroke weight does not scale with size. The same applies to figures. The features are there, they cost nothing, and most documents never switch them on.
How fonts reach this API
There is no font option on the render. A font arrives the way every other subresource arrives: your @font-face names a URL, the renderer fetches it while the document loads, and what was used is embedded in the output. So there is no font upload, no list of available fonts, no substitution control and no subsetting switch. It also means the two failures that actually stop a font are network-shaped rather than typographic: the URL has to be absolute and publicly reachable, and the fetch has to finish before the page is captured. Everything else on this page is decided in your stylesheet and in the font file itself.
The decisions
Reasons rather than a description of the code. Each of these has a default, and the default is chosen by the engine rather than by you.
- Use the high-level font-variant properties rather than raw feature tags where one exists. They are clearer and they degrade more sensibly when the font lacks the feature.
- Ask for real small capitals rather than transforming text to uppercase at a smaller size. The transformed version is lighter than its surroundings and it also changes what gets copied out of the document.
- Do not switch on a feature the font does not have and assume nothing happened. Sometimes nothing happens and sometimes a synthesised version appears, and you want to know which.
- Be careful with discretionary ligatures in a document that will be searched or extracted. Every substitution is a place the extracted text can differ from the set text.
- Keep feature settings in one place, applied at the body, rather than scattered per component where they will drift.
- Check the rendered document rather than the browser preview. A feature that applies on screen and not in the output is a specific and common failure worth catching.
What it looks like
A fragment, with the wrong version kept in a comment where the wrong version is the thing people actually write.
body {
/* Standard ligatures and kerning on: normal typesetting. */
font-variant-ligatures: common-ligatures;
font-kerning: normal;
}
/* Real small capitals: glyphs the designer drew, at the right weight. */
.legal-heading { font-variant-caps: small-caps; }
/* Not this: capitals scaled down are lighter than the text around them,
and the copied text comes out shouting.
.legal-heading { text-transform: uppercase; font-size: 0.8em; } */
/* Figures designed to sit in running prose rather than in a column. */
.prose { font-variant-numeric: oldstyle-nums proportional-nums; }
/* Figures for a column of money: lining and tabular. */
.amount { font-variant-numeric: lining-nums tabular-nums; }What people do instead
Faking small capitals with a text transform and a smaller size. It produces letters lighter than the body text they sit in, and it changes the underlying text to real capitals, so copying that heading out of the finished document gives you a line of shouting rather than the words as written.
How to find out rather than assume
Render the document, then select the affected text in a reader and copy it out. It should come back as the characters you set, in the case you set them. Then look at the small capitals next to the body text and check they are the same visual weight rather than lighter.
Frequently asked
Can I upload a font instead of serving one?
No. There is no font upload and no font list. The renderer fetches what your @font-face points at, so the file has to be somewhere it can reach over the network. In practice that means a public URL on your own asset host or a font service, and it means a font on a private path or behind an authenticated endpoint fails to load silently and the fallback is used instead.
How do I know which fonts ended up in the document?
Open the finished file in a reader and look at its document properties, which list the embedded fonts. That list is the truth: it says whether the face you meant was used, whether a fallback was substituted, and how many faces the document is carrying. It is a five second check and it catches most of the failures in this cluster.
Why does the font work in my browser and not in the render?
Almost always because the URL resolves for you and not for the renderer. A relative path, a local file, a development host, or an asset behind a login all work while you are looking at the page and none of them work when a machine somewhere else loads it. The fallback is then used and nothing reports an error, which is why the symptom is a document that looks subtly wrong rather than a render that failed.
Related font topics
The topics that cause each other, then the rest of the same group.
Why searching a PDF misses words containing fi and fl
A ligature is one glyph standing for two or more characters, and unless the font tells the reader which characters those were, the text comes back out wrong.
Why two fonts at the same size give different line heights
The ascent, descent and line gap recorded inside the font file, which decide how tall a line is before your stylesheet says anything.
Using a variable font in a paged document, and when not to
One file carrying a continuous range of weights instead of several files carrying fixed ones, which solves a download problem a generated document does not have.
Icon fonts in a PDF, and why an SVG is almost always better
Icons delivered as font glyphs, which look fine on the page and turn the document's extracted text into rubbish.
font-variant-numeric in paged output
The property behind this decision, with its real support status.
Every font topic
The full list, grouped by supply, engine behaviour, and what happens to the text afterwards.
Fonts reach a render the way every other subresource does, over the network from the URL you named. Render the document and look at what actually got embedded.