---
modificationDate: September 15, 2026
title: Font
description: A library that allows loading fonts at runtime and using them in React Native components.
sourceCodeUrl: 'https://github.com/expo/expo/tree/sdk-58/packages/expo-font'
packageName: 'expo-font'
iconUrl: '/static/images/packages/expo-font.png'
platforms: ['android', 'ios', 'tvos', 'web', 'expo-go']
---

This documentation is available as Markdown for AI agents and LLMs. See the [full Markdown index](/llms.txt) or append .md to any documentation URL.

# Expo Font

A library that allows loading fonts at runtime and using them in React Native components.

<AgentInstructions>

## Submitting Feedback

If you encounter errors, misleading or outdated information, report it so Expo can be improved:

Preferred command:
npx --yes submit-expo-feedback@latest --category docs --subject "/versions/v58.0.0/sdk/font/" "<actionable feedback>"

Direct HTTP fallback:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/v58.0.0/sdk/font/","feedback":"🤖 Agent feedback for docs: <specific, actionable description> (<model>, <harness>)"}'

Only submit when you have something specific and actionable to report. Try to give the most context.

## Navigation

When answering a related or follow-up question, use llms.txt to find the relevant page as Markdown (.md) instead of guessing.

You are here: Reference (v58.0.0) > Expo SDK (88 pages in this section)
Full documentation tree: [llms.txt](https://docs.expo.dev/llms.txt)

</AgentInstructions>
Android, iOS, tvOS, Web, Included in Expo Go

`expo-font` allows loading fonts from the web and using them in React Native components. See more detailed usage information in the [Fonts](/develop/user-interface/fonts.md) guide.

## Installation

```sh
# npm
npx expo install expo-font

# yarn
yarn expo install expo-font

# pnpm
pnpm expo install expo-font

# bun
bun expo install expo-font
```

If you are installing this in an [existing React Native app](/bare/overview.md), make sure to [install `expo`](/bare/installing-expo-modules.md) in your project.

## Configuration in app config

There are two ways to add fonts to your app: using the `expo-font` config plugin (recommended for Android and iOS) or loading them at runtime (which works across all platforms including web).

On Android and iOS, the plugin allows you to embed font files at build time which is more efficient than [`useFonts`](/versions/v58.0.0/sdk/font.md#usefonts) or [`loadAsync`](/versions/v58.0.0/sdk/font.md#loadasyncfontfamilyorfontmap-source). After you set up the config plugin and run [prebuild](/workflow/continuous-native-generation.md#usage), you can render custom fonts right away. The plugin can be configured in different ways, see the [Fonts](/develop/user-interface/fonts.md#with-expo-font-config-plugin) guide on how to use it.

### Example app.json with config plugin

```json app.json
{
  "expo": {
    "plugins": [
      [
        "expo-font",
        {
          "fonts": ["./path/to/file.ttf"],
          "android": {
            "fonts": [
              {
                "fontFamily": "Source Serif 4",
                "fontDefinitions": [
                  {
                    "path": "./path/to/SourceSerif4-ExtraBold.ttf",
                    "weight": 800
                  }
                ]
              },
              {
                "fontFamily": "Roboto Flex",
                "path": "./path/to/RobotoFlex.ttf",
                "fontDefinitions": [
                  { "weight": 400 },
                  { "weight": 700 },
                  { "weight": 400, "style": "italic", "axes": { "slnt": -10 } }
                ]
              }
            ]
          },
          "ios": {
            "fonts": ["./path/to/SourceSerif4-ExtraBold.ttf"]
          }
        }
      ]
    ]
  }
}
```

### Configurable properties

| Name | Default | Description |
| --- | --- | --- |
| `fonts` | `[]` | An array of font definitions to link to the native project. The paths should be relative to the project root. On Android, the file name becomes the font family name. On iOS, the font family name is always taken directly from the font file and may not be the same as the file name — follow the [naming advice](/develop/user-interface/fonts.md#how-to-determine-which-font-family-name-to-use) or use [`getLoadedFonts`](/versions/v58.0.0/sdk/font.md#getloadedfonts) to see what fonts are available. |
| `android` | `{}` | An object with a `fonts` array of font definitions to link to the native project on Android. Use the object syntax within `fonts` to embed [xml fonts](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml) with custom family name. |
| `ios` | `{}` | An object with a `fonts` array of font file paths to link to the native project on iOS. The font family name is taken directly from the font file. |

#### Are you using this library in an existing React Native app?

-   **Android:** Copy font files to **android/app/src/main/assets/fonts**.
-   **iOS**: See [Adding a Custom Font to Your App](https://developer.apple.com/documentation/uikit/adding-a-custom-font-to-your-app) in the Apple Developer documentation.

## Usage

If you don't want to use the [config plugin](/versions/v58.0.0/sdk/font.md#configuration-in-app-config), you can load a font at runtime with the `useFonts` hook, as shown in the snippet:

```tsx Example of loading and using a custom font
import { useFonts } from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import { Text, View, StyleSheet } from 'react-native';

SplashScreen.preventAutoHideAsync();

export default function App() {
  // Use `useFonts` only if you can't use the config plugin.
  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 (
    <View style={styles.container}>
      <Text style={{ fontFamily: 'Inter-Black', fontSize: 30 }}>Inter Black</Text>
      <Text style={{ fontSize: 30 }}>Platform Default</Text>
    </View>
  );
}

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

### Variable fonts

The `Roboto Flex` entry in the example above is a variable font: one file that holds many faces. You select a face with the `fontWeight` and `fontStyle` style props. Variable fonts also work with [`useFonts`](/versions/v58.0.0/sdk/font.md#usefonts). To learn more, see [Variable fonts](/develop/user-interface/fonts.md#variable-fonts) in the Fonts guide.

## API

```js
import * as Font from 'expo-font';
```

## Constants

### `useFonts`

Supported platforms: Android, iOS, tvOS, Web.

Type: `UseFontHook`

Load a map of fonts at runtime with [`loadAsync`](/versions/v58.0.0/sdk/font.md#loadasyncfontfamilyorfontmap-source). This returns `true` if the fonts are loaded and ready to use. It also returns an error if something went wrong, to use in development.

> Note, the fonts are not "reloaded" when you dynamically change the font map.

> A `fontFamily` loads once. Declare all of its faces in the same `useFonts` call. A later call for an already-loaded `fontFamily` adds none of its faces, even if that call lists more.

Example

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

On web, loading multiple weights or styles of the same family lets the browser select the correct face with the CSS `font-weight` and `font-style` properties:

```tsx
const [loaded, error] = useFonts([
  {
    fontFamily: 'Inter',
    fontDefinitions: [
      { path: require('./assets/fonts/Inter-Regular.otf'), weight: 400 },
      { path: require('./assets/fonts/Inter-Italic.otf'), weight: 400, style: 'italic' },
      { path: require('./assets/fonts/Inter-Bold.otf'), weight: 700 },
    ],
  },
]);
```

## Methods

### `getLoadedFonts()`

Supported platforms: Android, iOS, tvOS, Web.

Synchronously get all the fonts that have been loaded. This includes fonts that were bundled at build time using the config plugin, as well as those loaded at runtime using `loadAsync`.

Returns: `string[]`

Returns array of strings which you can use as `fontFamily` [style prop](https://reactnative.dev/docs/text#style).

### `isLoaded(fontFamily)`

Supported platforms: Android, iOS, tvOS, Web.

| Parameter | Type | Description |
| --- | --- | --- |
| `fontFamily` | `string` | The name used to load the `FontResource`. |

  

Synchronously detect if the font for `fontFamily` has finished loading.

Returns: `boolean`

Returns `true` if the font has fully loaded.

### `isLoading(fontFamily)`

Supported platforms: Android, iOS, tvOS, Web.

| Parameter | Type | Description |
| --- | --- | --- |
| `fontFamily` | `string` | The name used to load the `FontResource`. |

  

Synchronously detect if the font for `fontFamily` is still being loaded.

Returns: `boolean`

Returns `true` if the font is still loading.

### `loadAsync(fontFamilyOrFontMap, source)`

Supported platforms: Android, iOS, tvOS, Web.

| Parameter | Type | Description |
| --- | --- | --- |
| `fontFamilyOrFontMap` | [FontMap](/versions/v58.0.0/sdk/font.md#fontmap) | String, map of values that can be used as the `fontFamily` [style prop](https://reactnative.dev/docs/text#style) with React Native `Text` elements, or an array of [`FontFamilyDefinition`](/versions/v58.0.0/sdk/font.md#fontfamilydefinition)s for loading multiple faces per family. |
| `source`(optional) | [FontSource](/versions/v58.0.0/sdk/font.md#fontsource) | The font asset that should be loaded into the `fontFamily` namespace. |

  

An efficient method for loading fonts from static or remote resources which can then be used with the platform's native text elements. In the browser, this generates a `@font-face` block in a shared style sheet for fonts. No CSS is needed to use this method.

> **Note**: We recommend using the [config plugin](/versions/v58.0.0/sdk/font.md#configuration-in-app-config) instead whenever possible.

> **Note**: When the `fontFamily` is already loaded, this method resolves without replacing it. This applies across the string and array APIs, and across separate calls: a `fontFamily` loads once. Declare all of its faces in that one call. A later call for an already-loaded `fontFamily` adds none of its faces, even if that call lists faces the first call did not.

Returns: `Promise<void>`

Returns a promise that fulfils when the font has loaded. Often you may want to wrap the method in a `try/catch/finally` to ensure the app continues if the font fails to load.

### `renderToImageAsync(glyphs, options)`

Supported platforms: Android, iOS.

| Parameter | Type | Description |
| --- | --- | --- |
| `glyphs` | `string` | Text to be exported. |
| `options`(optional) | [RenderToImageOptions](/versions/v58.0.0/sdk/font.md#rendertoimageoptions) | RenderToImageOptions. |

  

Creates an image with provided text.

Returns: `Promise<RenderToImageResult>`

Promise which fulfils with image metadata.

## Interfaces

### `RenderToImageOptions`

Supported platforms: Android, iOS, tvOS, Web.

| Property | Type | Description |
| --- | --- | --- |
| color(optional) | `string` | Font color. Default: `'black'` |
| fontFamily(optional) | `string` | Font family name. Default: `system default` |
| lineHeight(optional) | `number` | Line height of the text. Accepts number in dp units. |
| size(optional) | `number` | Size of the font. Default: `24` |

### `RenderToImageResult`

Supported platforms: Android, iOS, tvOS, Web.

| Property | Type | Description |
| --- | --- | --- |
| height | `number` | Image height in dp. |
| scale | `number` | Scale factor of the image. Multiply the dp dimensions by this value to get the dimensions in pixels. |
| uri | `string` | The file uri to the image. |
| width | `number` | Image width in dp. |

## Types

### `FontFaceDefinition`

Supported platforms: Android, iOS, tvOS, Web.

A single font face that belongs to a [`FontFamilyDefinition`](/versions/v58.0.0/sdk/font.md#fontfamilydefinition). Use `weight` and `style` to distinguish faces of the same `fontFamily`, for example the bold or italic cut of a typeface.

| Property | Type | Description |
| --- | --- | --- |
| display(optional) | [FontDisplay](/versions/v58.0.0/sdk/font.md#fontdisplay) | Supported platforms: Web. Sets the [`font-display`](/versions/v58.0.0/sdk/font.md#fontdisplay) property for this face in the browser. |
| path | [FontSource](/versions/v58.0.0/sdk/font.md#fontsource) | The font asset to load for this face, in any format accepted by [`FontSource`](/versions/v58.0.0/sdk/font.md#fontsource). |
| style(optional) | `'normal' | 'italic' | 'oblique'` | On Android, the declared style used to select this face. When unset, the style read from the font file applies. On API levels below 29, only the family's default face (closest to a regular, upright weight and style) is loaded. On iOS, this value isn't used to select the face; iOS reads the style embedded in the font file's own metadata instead. On web, maps to the CSS `font-style` property. Leave unset for a variable font file that covers both upright and italic/oblique styles — a single value restricts the face to only that style. |
| weight(optional) | `number | string` | On Android, the declared weight used to select this face. When unset, the weight read from the font file applies. On API levels below 29, only the family's default face (closest to a regular, upright weight and style) is loaded. On iOS, this value isn't used to select the face; iOS reads the weight embedded in the font file's own metadata instead. On web, maps to the CSS `font-weight` property. A variable font file can also declare a weight range as `'<min> <max>'`, for example `'100 900'`. Leave unset for a variable font file that covers its full range of weights — a single value restricts the face to only that weight. Android and iOS ignore a range and read the weight from the font file instead. |

### `FontFamilyDefinition`

Supported platforms: Android, iOS, tvOS, Web.

Groups one or more [`FontFaceDefinition`](/versions/v58.0.0/sdk/font.md#fontfacedefinition)s under a single `fontFamily` name. Use this to load multiple weights or styles (for example regular, bold, and italic) of the same typeface so the browser can select the correct face with the CSS `font-weight` and `font-style` properties.

| Property | Type | Description |
| --- | --- | --- |
| fontDefinitions | [FontFaceDefinition[]](/versions/v58.0.0/sdk/font#fontfacedefinition) | The faces (for example different weights or styles) that make up `fontFamily`. |
| fontFamily | `string` | The name used as the `fontFamily` [style prop](https://reactnative.dev/docs/text#style) with React Native `Text` elements. |

### `FontMap`

Supported platforms: Android, iOS, tvOS, Web.

Literal type: `union`

The value accepted by [`useFonts`](/versions/v58.0.0/sdk/font.md#usefonts) and [`loadAsync`](/versions/v58.0.0/sdk/font.md#loadasyncfontfamilyorfontmap-source): a single `fontFamily` name, a map of `fontFamily` names to [`FontSource`](/versions/v58.0.0/sdk/font.md#fontsource)s, or an array of [`FontFamilyDefinition`](/versions/v58.0.0/sdk/font.md#fontfamilydefinition)s for loading multiple faces per family.

Acceptable values are: `string` | Record<string, [FontSource](/versions/v58.0.0/sdk/font.md#fontsource)\>

### `FontResource`

Supported platforms: Android, iOS, tvOS, Web.

An object used to dictate the resource that is loaded into the provided font namespace when used with [`loadAsync`](/versions/v58.0.0/sdk/font.md#loadasyncfontfamilyorfontmap-source).

| Property | Type | Description |
| --- | --- | --- |
| default(optional) | `string` | - |
| display(optional) | [FontDisplay](/versions/v58.0.0/sdk/font.md#fontdisplay) | Supported platforms: Web. Sets the [`font-display`](/versions/v58.0.0/sdk/font.md#fontdisplay) property for a given typeface in the browser. |
| style(optional) | `'normal' | 'italic' | 'oblique'` | Sets the face's `style` when the resource is the `path` of a [`FontFaceDefinition`](/versions/v58.0.0/sdk/font.md#fontfacedefinition) and the face doesn't declare its own. Outside of a font family definition, only the browser uses this value, as the CSS `font-style` property. |
| uri(optional) | `string | number` | - |
| weight(optional) | `number | string` | Sets the face's `weight` when the resource is the `path` of a [`FontFaceDefinition`](/versions/v58.0.0/sdk/font.md#fontfacedefinition) and the face doesn't declare its own. Outside of a font family definition, only the browser uses this value, as the CSS `font-weight` property. |

### `FontSource`

Supported platforms: Android, iOS, tvOS, Web.

Literal type: `union`

The different types of assets you can provide to the [`loadAsync()`](/versions/v58.0.0/sdk/font.md#loadasyncfontfamilyorfontmap-source) function. A font source can be a URI, a module ID, or an Expo Asset.

Acceptable values are: `string` | `number` | [Asset](/versions/latest/sdk/asset.md#asset) | [FontResource](/versions/v58.0.0/sdk/font.md#fontresource)

### `ServerFontResourceDescriptor`

Supported platforms: Android, iOS, tvOS, Web.

Type: `object` shaped as below:

| Property | Type | Description |
| --- | --- | --- |
| css | `string` | - |
| id | `string` | - |
| type | `'style'` | - |

Or `object` shaped as below:

| Property | Type | Description |
| --- | --- | --- |
| as | `'font'` | - |
| crossOrigin(optional) | `'anonymous' | 'use-credentials' | undefined` | - |
| href | `string` | - |
| rel | `'preload'` | - |
| type | `'link'` | - |

## Enums

### `FontDisplay`

Supported platforms: Web.

Sets the [font-display](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display) for a given typeface. The default font value on web is `FontDisplay.AUTO`. Even though setting the `fontDisplay` does nothing on native platforms, the default behavior emulates `FontDisplay.SWAP` on flagship devices like iOS, Samsung, Pixel, etc. Default functionality varies on One Plus devices. In the browser this value is set in the generated `@font-face` CSS block and not as a style property meaning you cannot dynamically change this value based on the element it's used in.

#### `AUTO`

`FontDisplay.AUTO = "auto"`

**(Default)** The font display strategy is defined by the user agent or platform. This generally defaults to the text being invisible until the font is loaded. Good for buttons or banners that require a specific treatment.

#### `BLOCK`

`FontDisplay.BLOCK = "block"`

The text will be invisible until the font has loaded. If the font fails to load then nothing will appear - it's best to turn this off when debugging missing text.

#### `FALLBACK`

`FontDisplay.FALLBACK = "fallback"`

Splits the behavior between `SWAP` and `BLOCK`. There will be a [100ms timeout](https://developers.google.com/web/updates/2016/02/font-display?hl=en) where the text with a custom font is invisible, after that the text will either swap to the styled text or it'll show the unstyled text and continue to load the custom font. This is good for buttons that need a custom font but should also be quickly available to screen-readers.

#### `OPTIONAL`

`FontDisplay.OPTIONAL = "optional"`

This works almost identically to `FALLBACK`, the only difference is that the browser will decide to load the font based on slow connection speed or critical resource demand.

#### `SWAP`

`FontDisplay.SWAP = "swap"`

Fallback text is rendered immediately with a default font while the desired font is loaded. This is good for making the content appear to load instantly and is usually preferred.

## Error codes

| Code | Description |
| --- | --- |
| ERR_FONT_API | If the arguments passed to `loadAsync` are invalid. |
| ERR_FONT_SOURCE | The provided resource was of an incorrect type. |
| ERR_WEB_ENVIRONMENT | The browser's `document` element doesn't support injecting fonts. |
| ERR_DOWNLOAD | Failed to download the provided resource. |
| ERR_FONT_FAMILY | Invalid font family name was provided. |
| ERR_UNLOAD | Attempting to unload fonts that haven't finished loading yet. |
