HomeGuidesReferenceLearn
ArchiveExpo SnackDiscord and ForumsNewsletter

Fonts

Edit this page

Learn how to integrate custom fonts in your app using local files or Google Font packages


Android and iOS come with their own set of platform fonts. To provide a consistent user experience and enhance your app's branding, you can use custom fonts.

This guide covers different ways you can add and load a custom font into your project and also provides additional information related to fonts.

Add a custom font

There are two ways you can add a custom font into your project:

Supported font formats

Expo SDK officially supports OTF and TTF font formats across Android, iOS and web platforms. If your font is in another font format, you have to set up advanced configuration to support that format in your project.

How to choose between OTF and TTF

If the font you're using have both OTF and TTF versions, prefer OTF. The .otf files are smaller than .ttf files. Sometimes, OTF also renders slightly better in certain contexts.

Use a local font file

Copy the file into your project's assets/fonts directory.

assets/fonts directory path is a common convention in React Native apps to put font files. You can place these files if elsewhere if you follow a custom convention.

Two ways to use the local font file your project:

With expo-font config plugin

The expo-font config plugin allows embedding one or more font files in your project's native code. This method has a few benefits:

  • Available immediately when the app starts on a device.
  • No additional code required to load fonts in a project asynchronously when the app starts.
  • Fonts are consistently available across all devices where the app is installed because they're bundled within the app.

However, this method also has some limitations:

  • Doesn't work with Expo Go since this method requires creating a development build.
  • Only available for SDK 50 and above.

To embed a font in a project, follow the steps below:

1

After adding a custom font file in your project, install the expo-font library.

Terminal
- npx expo install expo-font

2

Add the config plugin to your app config file. The configuration must contain the path to the font file using fonts property which takes an array of one or more font files. The path to each font file is relative to the project's root. For example, in the following configuration, Inter-Black.otf font file's path is defined.

app.json
{
  "expo": {
    "plugins": [
      [
        "expo-font",
        {
          "fonts": ["./assets/fonts/Inter-Black.otf"]
        }
      ]
    ]
  }
}

3

After embedding the font with the config plugin, create a new development build and install it on your device or Android Emulator or iOS Simulator.

You can use that font on <Text> by using fontFamily style prop. For example, the <Text> uses the Inter-Black as the font family:

<Text style={{ fontFamily: 'Inter-Black' }}>Inter Black.</Text>

How to determine which font family name to use

On Android, the font family name is the same as of the font file (without the extension). On iOS, the font family name is read from the font file itself.

We recommend naming the font file same as its PostScript name so the font family name is consistent on both platforms.

What is PostScript name of a font file?

The PostScript name of a font file is a unique identifier assigned to the font that follows Adobe's PostScript standard. It is used by operating systems and apps to refer to the font. It is not a font's display name.

For example, Inter Black font file's PostScript name is Inter-Black.

Using this method in a bare React Native project?
  • Android: Copy font files to android/app/src/main/assets/fonts.
  • iOS: See Adding a Custom Font to Your App in the Apple Developer documentation.

With useFonts hook

The useFonts hook from expo-font library allows loading the font file asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized.

It works with all Expo SDK versions and with Expo Go. To load a font in a project using useFonts hook, follow the steps below:

1

After adding a custom font file in your project, install the expo-font and expo-splash-screen libraries.

Terminal
- npx expo install expo-font expo-splash-screen

The expo-splash-screen library provides SplashScreen component that you can use to prevent rendering the app until the font is loaded and ready.

2

Map the font file using the useFonts hook in a top level component such as the root layout (app/layout.tsx) file in your project:

app/_layout.tsx
import { useFonts } from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import {useEffect} from 'react';

SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  const [loaded, error] = useFonts({
    'Inter-Black': require('./assets/fonts/Inter-Black.otf'),
  });

  useEffect(() => {
    if (loaded || error) {
      SplashScreen.hideAsync();
    }
  }, [loaded, error]);

  if (!loaded && !error) {
    return null;
  }

  return (
    %%placeholder-start%%... %%placeholder-end%%
  )
}

3

Use the font on the <Text> by using fontFamily style prop in a React component:

<Text style={{ fontFamily: 'Inter-Black' }}>Inter Black</Text>

Use Google Fonts

Expo has first-class support for all fonts listed in Google Fonts. They are available using @expo-google-fonts library. With any of the font package from this library, you can quickly integrate that font and its variants.

Two ways to use a Google Font in your project:

With expo-font config plugin

Note: Embedding a Google Font using expo-font config plugin has same benefits and limitations as embedding a custom font on your own. See using a local font file with expo-font config plugin for more information.

1

Install the font package. For example, to use Inter Black font, install the @expo-google-fonts/inter package with the command below.

Terminal
- npx expo install expo-font @expo-google-fonts/inter

2

Add the config plugin to your app config file. The configuration must contain the path to the font file using fonts property which takes an array of one or more font files. The path to the font file is defined from the font package inside the node_modules directory. For example, if you have a font package named @expo-google-fonts/inter, then the name of the file is Inter_900Black.ttf.

app.json
{
  "plugins": [
    [
      "expo-font",
      {
        "fonts": ["node_modules/@expo-google-fonts/inter/Inter_900Black.ttf"]
      }
    ]
  ]
}

3

After embedding the font with the config plugin, create a new development build and install it on your device or Android Emulator or iOS Simulator.

On Android, you can use the font file name. For example, Inter_900Black. On iOS, use the font and its weight name (PostScript name). The example below demonstrates how to use Platform to select the correct font family name for each platform:

import { Platform } from 'react-native';

// Inside a React component:
<Text
  style={{
    fontFamily: Platform.select({
      android: 'Inter_900Black',
      ios: 'Inter-Black',
    }),
  }}>
  Inter Black
</Text>

With useFonts hook

Note: Loading a Google Font using useFonts hook has same benefits and limitations as embedding a custom font on your own. See using a local font file with useFonts hook for more information.

Each google Fonts package provides the useFonts hook to load the fonts asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized. The font package also imports the font file so you don't have to explicitly import it.

1

Install the Google Fonts package, expo-font and expo-splash-screen libraries.

Terminal
- npx expo install @expo-google-fonts/inter expo-font expo-splash-screen

The expo-splash-screen library provides SplashScreen component that you can use to prevent rendering the app until the font is loaded and ready.

2

After installing the font package, map the font using the useFonts hook in a top level component such as the root layout (app/layout.tsx) file in your project:

app/_layout.tsx
// Rest of the import statements
import { Inter_900Black, useFonts } from '@expo-google-fonts/inter';
import * as SplashScreen from 'expo-splash-screen';
import {useEffect} from 'react';

SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  const [loaded, error] = useFonts({
    Inter_900Black,
  });

  useEffect(() => {
    if (loaded || error) {
      SplashScreen.hideAsync();
    }
  }, [loaded, error]);

  if (!loaded && !error) {
    return null;
  }

  return (
    %%placeholder-start%%... %%placeholder-end%%
  )
}

3

Use the font on the <Text> by using fontFamily style prop in a React component:

<Text style={{ fontFamily: 'Inter_900Black' }}>Inter Black</Text>

Additional information

Minimal example

expo-font usage

See usage section in Expo Fonts API reference for a minimal example of using a custom font.

Beyond OTF and TTF

If your font is in format other than OTF or TTF, you have to customize the Metro bundler configuration to include it as an extra asset for it to work. In some cases, rendering a font format that a platform doesn't support may cause your app to crash.

For reference, the following table provides the list formats that work on each native platform:

FormatAndroidiOSWeb
bdf
dfont
eot
fon
otf
ps
svg
ttc
ttf
woff
woff2

Platform built-in fonts

If you don't want to use a custom font by specifying a fontFamily, platform's default font will be used. Each platform has a set of built in fonts. On Android, the default font is Roboto. On iOS, it's SF Pro.

A platform's default font is usually easy-to-read. However, don't be surprised when the system default font is changed to use another font that is not easy to read. In this case, use your custom font so you have precise control over what the user will see.

Handle @expo/vector-icons initial load

When the icons from @expo/vector-icons library load for the first time, they appear as invisible icons in your app. Once they load, they're cached for all the app's subsequent usage. To avoid showing invisible icons on your app's first load, preload during the initial loading screen with useFonts. For example:

app/_layout.tsx
import { useFonts } from 'expo-font';
import Ionicons from '@expo/vector-icons/Ionicons';

export default function RootLayout() {
  useFonts([require('./assets/fonts/Inter-Black.otf', FontAwesome.font)]);

  return (
    %%placeholder-start%%... %%placeholder-end%%
  )
}

Now, you can any icon from the Ionicons library in a React component:

<Ionicons name="checkmark-circle" size={32} color="green" />
Icons

Learn how to use various types of icons in your Expo app, including vector icons, custom icon fonts, icon images, and icon buttons.

Loading a remote font directly from the web

If you're loading remote fonts, make sure they are being served from an origin with CORS properly configured. If you don't do this, your remote font might not load properly on the web platform.

Loading fronts from a local asset is the safest way to load a font in your app. When including fonts as local assets, after you submit your app to the app stores, these fonts are bundled with the app download and will be available immediately. You don't have to worry about CORS or other potential issues.

However, loading a font file directly from web is done by replacing the require('./assets/fonts/FontName.otf') with the URL of your font as shown in the example below.

Using a remote font
import { useFonts } from 'expo-font';
import { Text, View, StyleSheet } from 'react-native';

export default function App() {
  const [loaded, error] = useFonts({
    'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12',
  });

  if (!loaded || !error) {
    return null;
  }

  return (
    <View style={styles.container}>
      <Text style={{ fontFamily: 'Inter-SemiBoldItalic', fontSize: 30 }}>Inter SemiBoldItalic</Text>
      <Text style={{ fontSize: 30 }}>Platform Default</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});