Fonts
React-pdf is shipped with a Font module that enables to load fonts from different sources, handle how words are wrapped and defined an emoji source to embed these glyphs on your document.
You can define multiple sources for the same font family, each with a different fontStyle or fontWeight. React-pdf will pick the appropriate font for each <Text /> based on its style and the registered fonts.
Currently,
- only TTF and WOFF fonts files are supported. A list of available TTF fonts from Google can be found here.
- Any OpenType Variable fonts (such as Noto Sans variable weights font) does not work properly because PDF 2.0 spec does not support those. It is required to register separate fonts using 'fonts' property (explained in below).
import { StyleSheet, Font } from '@react-pdf/renderer';
// Register font
Font.register({ family: 'Roboto', src: source });
// Reference font
const styles = StyleSheet.create({
title: {
fontFamily: 'Roboto',
},
});OpenType font features
The fontFeatureSettings style property picks which OpenType features the font applies: tabular figures that line up in a column, slashed zeros, real fractions, small capitals, alternate ligatures, and whatever else the font was built with.
Pass an array to switch features on, or an object to set them one by one:
const styles = StyleSheet.create({
amounts: { fontFeatureSettings: ['tnum', 'zero'] },
plain: { fontFeatureSettings: { calt: 0, kern: 0 } },
});Kerning and ligatures (kern, liga, clig, rlig, calt) are applied by default, so the object form is the only way to turn one back off. Like fontFamily, the property is inherited: set it on a View or Page and every Text inside picks it up.
Common tags
| Tag | Effect |
|---|---|
tnum | Tabular figures: every digit the same width, so columns align |
onum | Old-style figures, with ascenders and descenders |
lnum | Lining figures, all at cap height |
zero | Slashed zero |
frac | Turns 1/2 into a single fraction glyph |
sups / subs | Superscript and subscript forms |
smcp / c2sc | Small capitals, from lowercase and from capitals |
case | Case-sensitive forms: punctuation raised to match capitals |
liga / dlig | Standard and discretionary ligatures |
calt | Contextual alternates |
swsh | Swashes |
hist | Historical forms |
ss01–ss20 | Stylistic sets, whose meaning is up to the font |
kern | Kerning between letter pairs |
Which of these do anything depends on the font file. The standard fonts (Helvetica, Times-Roman, Courier) support none of them, and a registered font only carries the features it shipped with; asking for a tag it doesn't have is silently ignored. To see what a font actually offers:
import fontkit from 'fontkit';
fontkit.openSync('Inter-Regular.ttf').availableFeatures;
// ['aalt', 'calt', 'case', 'ccmp', 'dlig', 'frac', 'ss01', …, 'tnum', 'zero', 'kern']register
Fonts really make the difference when it comes on styling a document. For obvious reasons, react-pdf cannot ship a wide amount of them. Here's a list of available font families that are supported out of the box:
CourierCourier-BoldCourier-ObliqueCourier-BoldObliqueHelveticaHelvetica-BoldHelvetica-ObliqueHelvetica-BoldObliqueTimes-RomanTimes-BoldTimes-ItalicTimes-BoldItalic
In case you want to use a different font, you may load additional font files from many different sources via the register method very easily.
import { Font } from '@react-pdf/renderer'
Font.register({ family: 'FamilyName', src: source, fontStyle: 'normal', fontWeight: 'normal', fonts?: [] });source
Specifies the source of the font. This can either be a valid URL, or an absolute path if you're using react-pdf on Node.
family
Name to which the font will be referenced on styles definition. Can be any unique valid string
fontStyle
Specifies to which font style the registered font refers to.
| Value | Description |
|---|---|
| normal | Selects a font that is classified as normal Default |
| italic | Selects a font that is classified as italic. If no italic version of the font is registered, react-pdf will fail when a style of this type is present |
| oblique | Selects a font that is classified as oblique. If no oblique version of the font is registered, react-pdf will fail when a style of this type is present |
fontWeight
Specifies the registered font weight.
| Value | Description |
|---|---|
| thin | Equals to value 100 |
| ultralight | Equals to value 200 |
| light | Equals to value 300 |
| normal | Equals to value 400 Default |
| medium | Equals to value 500 |
| semibold | Equals to value 600 |
| bold | Equals to value 700 |
| ultrabold | Equals to value 800 |
| heavy | Equals to value 900 |
| number | Any integer value between 0 and 1000 |
When the exact font weight is not registered for a given text, react-pdf will fallback to the nearest registered weight in the same way browsers do. More information here
fonts
In many cases you will end up registering multiple sources for the same font family (each with different font-style and font-weight for instance). As an alternative of calling Font.register for each of this, you can use the fonts attribute to register them all at once:
Font.register({
family: 'Roboto',
fonts: [
{ src: source1 }, // font-style: normal, font-weight: normal
{ src: source2, fontStyle: 'italic' },
{ src: source3, fontStyle: 'italic', fontWeight: 700 },
],
});registerHyphenationCallback
Enables you to have fine-grained control over how words break, passing your own callback and handle all that logic for yourself:
import { Font } from '@react-pdf/renderer';
const hyphenationCallback = (word) => {
// Return word parts in an array
};
Font.registerHyphenationCallback(hyphenationCallback);To hyphenate a language other than the default en-us, register a syllables function from @react-pdf/hyphenate:
import { Font } from '@react-pdf/renderer';
import { syllables } from '@react-pdf/hyphenate/de';
Font.registerHyphenationCallback(syllables);Disabling hyphenation
You can easily disable word hyphenation by just returning the same word as it is passed to the hyphenation callback
Font.registerHyphenationCallback((word) => [word]);hyphenationPenalty
In some cases you can avoid the need for custom break logic by tuning/adjusting at what level a word is sliced for hyphenation. Providing the hyphenationPenalty prop on Text components allows you to tune this. Higher values makes the algorithm more reluctant to break words across lines:
import { Text } from '@react-pdf/renderer';
<Text hyphenationPenalty={200}>
Lorem ipsum dolor sit amet consectetur adipiscing elit
</Text>;It defaults to 100 for justified text and 600 otherwise. Setting it to Infinity disables automatic hyphenation entirely for that text block, so lines break only at word boundaries:
<Text hyphenationPenalty={Infinity}>
Lorem ipsum dolor sit amet consectetur adipiscing elit
</Text>registerEmojiSource
PDF documents do not support color emoji fonts. This is a bummer for the ones out there who love their expressiveness and simplicity. The only way of rendering this glyphs on a PDF document, is by embedding them as images.
React-pdf makes this task simple by enabling you to use a CDN from where to download emoji images. All you have to do is setup a valid URL (we recommend using Twemoji for this task), and react-pdf will take care of the rest:
import { Font } from '@react-pdf/renderer';
Font.registerEmojiSource({
format: 'png',
url: 'https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/',
});Protip: react-pdf will need a internet connection to download emoji's images at render time, so bare that in mind when choosing to use this API