Editor’s note: This article was last updated by Chimezie Innocent on 16 September 2024 to cover common errors when working with custom fonts in React Native, including extended font loading times, using incorrect paths for font files, and more.
Fonts are the building blocks of a great user experience. Using custom fonts can provide your apps with a unique identity, helping your project stand out in a competitive marketplace.
In this guide, we will explore ways to add custom fonts in a React Native app using Google Fonts. To follow along, you should be familiar with the basics of React Native or the Expo SDK, including JSX, components (class and functional), and styling. You can also follow the GitHub repositories for this project to follow how to use the React Native CLI and Expo.
For our project, we will add custom fonts to a React Native CLI project by building a basic application using Google Fonts. Google Fonts is a library for free, open source fonts that can be used while designing web and mobile applications.
To bootstrap the React Native CLI project, run the following command in your terminal:
npx react-native@latest init CustomFontCLI
CustomFontCLI
is the name of our project folder. Once the project has been successfully installed, you will see the image below:
Open your project in your preferred IDE to get started. In this tutorial, we will use VS Code.
Once the project has been bootstrapped, we will move on to getting the fonts we want to use. We’ll go over how to import them and use them in our project.
In this project, we will demonstrate custom font integration using two fonts: Quicksand and Raleway, which you can find on Google Fonts.
Find your desired fonts in Google Fonts, select the styles you want (e.g., Light 300, Regular 400, etc.), and download the entire font folder using the Download all button:
The folder will be downloaded as a ZIP file with a font folder. Inside the folder, there is a static folder where all the TTF files reside. Copy and keep the TTF files.
In the next section, we will go through integrating these fonts’ TTF files into our React Native CLI project.
Create an assets
folder in the root directory of your project, with a subfolder called fonts
. Then, paste all the TTF files you copied from the static folder earlier into the fonts
folder of your project:
Next, create a react-native.config.js
file in the root directory and paste the code below inside it:
module.exports = { project: { ios: {}, android: {}, }, assets: ['./assets/fonts'], };
Adjust the assets path according to your font directory. Also, make sure your file is named correctly.
We have successfully integrated the font files into our project. Now we need to link them so we’ll be able to use them in any files inside the project. To do that, run the following command:
npx react-native-asset
Once the assets have been successfully linked, you should see the following message in your terminal:
Then, in your App.js
file, paste the following code:
import {StyleSheet, Text, View} from 'react-native'; import React from 'react'; const App = () => { return ( <View style={styles.container}> <Text style={styles.quicksandRegular}> This text uses a quick sand font </Text> <Text style={styles.quicksandLight}> This text uses a quick sand light font </Text> <Text style={styles.ralewayThin}> This text uses a thin italic raleway font </Text> <Text style={styles.ralewayItalic}> This text uses a thin italic raleway font </Text> </View> ); }; export default App; const styles = StyleSheet.create({ container: { backgroundColor: 'lavender', flex: 1, justifyContent: 'center', alignItems: 'center', }, quicksandLight: { fontFamily: 'Quicksand-Light', fontSize: 20, }, quicksandRegular: { fontFamily: 'Quicksand-Regular', fontSize: 20, }, ralewayItalic: { fontFamily: 'Raleway-Italic', fontSize: 20, }, ralewayThin: { fontFamily: 'Raleway-ThinItalic', fontSize: 20, }, });
This is a basic App.js
file with four texts being styled, each by different font styles of Raleway and Quicksand. Essentially, we are rendering the JSX with four texts to display on the screen and React Native’s StyleSheet API to append different fontFamily
styles to each of the Text
components.
Let’s see the output:
In this section, we will learn how to use custom fonts with Expo. Expo supports two font formats, OTF and TTF, which work consistently on iOS, Android, and the web. If you have your font in another format, you’ll need advanced configurations.
First, create a new Expo project by running this command:
npx create-expo-app@latest /* OR */ npx create-expo-app my-app
Once the project has been successfully installed, start the development server by running npm run start
and choose either the iOS or Android option to open your project.
You should see this when your simulator finishes loading the project:
useFonts
In React Native, the useFonts
Hook is the hook that allows you to load and use custom fonts. It takes an object where the key is the name you want to use to reference the font, and the value is the required statement pointing to the font file.
The syntax looks like this:
useFonts({ string, FontSource })
In this section, we will see how to add Google Fonts to our application. To add Google Fonts like Raleway and Quicksand, we will install these two packages using the commands below:
npx expo install @expo-google-fonts/raleway @expo-google-fonts/quicksand
If you have other Google Fonts you want to use, you can check here for the available fonts with Expo support.
In your App.js
file, paste the following code block:
import { useFonts } from "expo-font"; import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, View } from "react-native"; import { Raleway_200ExtraLight } from "@expo-google-fonts/raleway"; import { Quicksand_300Light } from "@expo-google-fonts/quicksand"; export default function App() { const [fontsLoaded] = useFonts({ Raleway_200ExtraLight, Quicksand_300Light, }); if (!fontsLoaded) { return <Text>Loading fonts...</Text>; } return ( <View style={styles.container}> <Text>This text has default style</Text> <Text style={styles.raleway}>This text uses Raleway Font</Text> <Text style={styles.quicksand}>This text uses QuickSand Font</Text> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, raleway: { fontSize: 20, fontFamily: "Raleway_200ExtraLight", }, quicksand: { fontSize: 20, fontFamily: "Quicksand_300Light", }, });
Here, we imported Raleway_200ExtraLight
and Quicksand_300Light
from their respective packages. We use the useFonts
Hook to load these custom fonts asynchronously. The result from the useFonts
Hook is an array of Boolean values that was destructured using the syntax const [fontsLoaded]
to access the Boolean value that it returns.
If the font(s) is successfully loaded, the result will be [true, null]
, which means fontsLoaded
is true. If unsuccessful, it will return [false, null]
. And if the font is not loaded yet, we’ll return a Loading
text.
If the fonts that are passed to the useFont
Hook (as shown in the code block above) have loaded, then render the app, and the font we specified should be used.
Let’s see what this looks like in our simulator:
Let’s say you have a personal React Native project you are building and you have been given custom fonts that are not among the available Google Fonts supported by Expo.
First, you will need to download the font
file into your project and install the expo-font
package. For this tutorial, I downloaded Source Code Pro from FontSquirrel as my custom font.
Create a folder called assets
and, within it, create a fonts
folder, just like you did with the React Native CLI. Then, move the font files from the fonts
folder into your project like so:
In your App.js
file, paste the following code:
import { useFonts } from "expo-font"; import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, View } from "react-native"; export default function App() { const [fontsLoaded] = useFonts({ "SourceCodePro-ExtraLight": require("./assets/fonts/SourceCodePro-ExtraLight.otf"), "SourceCodePro-LightIt": require("./assets/fonts/SourceCodePro-LightIt.otf"), }); if (!fontsLoaded) { return <Text>Loading fonts...</Text>; } return ( <View style={styles.container}> <Text style={styles.default}>This text has default style</Text> <Text style={styles.sourcepro}>This text uses Source Pro Font</Text> <Text style={styles.sourceprolight}>This text uses Source Pro Font</Text> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, default: { fontSize: 20, }, sourcepro: { fontSize: 20, fontFamily: "SourceCodePro-ExtraLight", }, sourceprolight: { fontSize: 20, fontFamily: "SourceCodePro-LightIt", }, });
Just like with Google Fonts integration, the useFonts
Hook is used to load the font files from the font
folder, which returns a true
or false
value based on whether the font is loaded successfully or not.
If fontsLoaded
is not true, i.e., the fonts specified within the useFonts
Hook have not been loaded successfully, we will return a Loading…
text. Otherwise, we render the app component and use the custom font(s) that has been loaded:
As shown in the simulator output above, the first text that has the default
style uses the default fontFamily
style, while the following two texts use the SourceCodePro-ExtraLight
and SourceCodePro-Light
font family that has been used to style the text, respectively.
When working with custom fonts in React Native, there might be some drawbacks you’ll encounter:
This happens when the UI or page is rendered before the font(s) is loaded. This leads to fallback fonts appearing, i.e., the default font of your mobile device. To fix this issue, use conditional rendering to render the app only after the fonts are loaded. We can see this applied throughout this article.
If the fonts are not ready, render a loading screen or an ActivityIndicator
:
import { useFonts } from "expo-font"; export default function App() { const [fontsLoaded] = useFonts({ "SourceCodePro-ExtraLight": require("./assets/fonts/SourceCodePro-ExtraLight.otf"), "SourceCodePro-LightIt": require("./assets/fonts/SourceCodePro-LightIt.otf"), }); if (!fontsLoaded) { return <Text>Loading fonts...</Text>; } return ( <View style={styles.container}> // application codes </View> ); }
As discussed in earlier sections, it’s crucial that font family names are consistent. For example, if you import a font as SourceCodePro-ExtraLight.otf
but then load it into the application under a different path or file name, such as /assets/fonts/SourceCodePro-ExtraLight.ttf
, this will cause the application to throw an error because there has been a fontFamily
name mismatch.
Using the wrong path for your font file will also cause the application to throw an error. Double-check the file structure and ensure the paths matches the exact location of the font file. Place your fonts in a /assets/fonts/
folder for easy matches, like /assets/fonts/SourceCodePro-ExtraLight.ttf
.
When working with custom fonts, it’s important to verify that the system you’re working on (iOS, Android, or web) supports the font format you are using (e.g., .ttf, .otf). If not, unexpected errors may occur during development.
When adding custom fonts to your React Native applications, be mindful of their file size (measured in kb/mb). Large font files can significantly increase an app’s loading time, especially when custom fonts are being loaded.
Hence, minimize the number of custom fonts you load by using a single font family with different weights (regular, bold, italic, etc.) rather than multiple unrelated ones or using a full zip folder.
This is when the fontWeight
or fontStyle
properties do not apply because the loaded font doesn’t support the variations (bold, italic, regular).
Let’s say you downloaded a zip file of SpaceMono font. It comes in different variations such as SpaceMono-Bold.ttf
, SpaceMono-Regular.ttf
, SpaceMono-Light.ttf
, and so on. If you need a bold weight of the font, then you need to use the SpaceMono-Bold.ttf
font or you will run into this issue. Most custom fonts are explicitly named with their weights or styles, so use the one you need to avoid this issue.
When building standalone apps (for Google PlayStore or Apple’s App Store), it is good to include the expo-font
plugin in app.json
. This is because the expo configuration helps ensure that Expo knows how to handle the fonts and bundle them properly. To do that, add the code below to your app.json
config file:
// app.json { "expo": { "plugins": [ [ "expo-font", { "fonts": ["./assets/fonts/Inter-Black.otf"] // your font's path } ] ] } }
Integrating custom fonts in React Native applications is not just a technical enhancement but a strategic approach to improving user experience. Whether using Expo or the React Native CLI, the process will significantly contribute to your app’s aesthetic and usability.
Check out the GitHub repo for this project using the React Native CLI and Expo.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowJavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.
Build a real-time image background remover in Vue using Transformers.js and WebGPU for client-side processing with privacy and efficiency.
6 Replies to "How to add custom fonts in React Native"
In RN 0.69 link command was removed so you should pass by npx react-native-asset to link you custom fonts
thanks for the tip
how to support multiple font weight?
react-native link is deprecated
run npx react-native-asset
check https://stackoverflow.com/questions/43021540/custom-font-not-working-in-react-native
Good article. I also want to point out that we must use the appropriate fontWeight for each font family. Otherwise, this may be an error.
Thankyou, well explained đź‘Ť