Skip to main content

Custom font

So far we've been using the default system font for each platform: that is, San Francisco on iOS and Roboto on Android. In order to use a custom font we need to bundle the font files with our application.

There's two ways of including custom fonts with Expo:

  1. load the font at runtime with the useFonts hook - this exists to make custom fonts possible in Expo Go and loads the font in asynchronously at runtime
  2. using the expo-font config plugin - available only with development builds, bundles the font files in the native bundle so they're always available

As we're on team Development Build now, we'll go with option number two! Format-wise, you can use either OTF and TTF formats. If the font you're using has both, choose OTF as the .otf files are smaller than .ttf files.

Config plugins

If you're using prebuild (that is, generating your native projects instead of checking them in), config plugins and mods are the tools you use to change anything you might need to in the native directories during prebuild.

Most React Native projects (like expo-font) come with a config plugin if one is needed for the library to work. If you need to use a library that requires native setup, but doesn't include a config plugin, you can build one yourself.

Google Fonts is a vast and free resource for custom fonts you can use and actually all fonts are available from @expo-google-fonts so you don't need to download them manually.

Let's take this font called "Caveat" from Google Fonts - it would be nice to use for our tagline.

Install libraries

npx expo install expo-font @expo-google-fonts/caveat 

Add the config plugin

Update: app.json
+++ b/app.json
@@ -39,6 +39,12 @@
}
}
}
+ ],
+ [
+ "expo-font",
+ {
+ "fonts": ["node_modules/@expo-google-fonts/caveat/Caveat_400Regular.ttf"]
+ }
]
]
}
diff --

Rebuild

Now we'll need to prebuild and rebuild so this font file could be incorporated within the native app.

npx expo prebuild --clean --platform ios
# or
npx expo prebuild --clean --platform android

And rebuild the native app

npx expo run:ios
## or
npx expo run:android

Use the new font family in code

Now this is where things differ between platforms. Recall that the filename of the font we installed was Caveat_400Regular.

On Android, you can simply use the filename, so fontFamily: "Caveat_400Regular".

On iOS, font family name is read from the font file itself. Namely, the font's PostScript name: it is a unique identifier assigned to the font that follows Adobe's PostScript standard (often different from the font's filename and display name). So on iOS the font family will instead be "Caveat-Regular"

We can use Platform.select to pick the correct value for each platform.

Update: app/onboarding.tsx
@@ -56,8 +63,12 @@ const styles = StyleSheet.create({
textAlign: "center",
},
tagline: {
- fontSize: 24,
+ fontSize: 34,
color: theme.colorWhite,
textAlign: "center",
- }
+ fontFamily: Platform.select({
+ ios: "Caveat-Regular",
+ android: "Caveat_400Regular",
+ }),
+ },
});
Naming fonts

If you can, name your font files after their PostScript name: then the same name will work on iOS and Android.

Checkpoint

AndroidiOS
Checkpoint