Custom fonts in ArcGIS Experience Builder let you extend typography beyond system and default theme families. You can load hosted web fonts (e.g. Google Fonts) or bundle local font files, then register them in variables.json so they appear in Theme Settings. Follow the workflow below to choose, load, register, apply, and optimize fonts while maintaining performance and accessibility.
1. Select or load fonts
You have two main options to load custom fonts into your theme:
Hosted fonts
You can use hosted fonts, such as Google Fonts, by obtaining the stylesheet URL and adding it to your theme.
Example generated URL (full):
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">Recommended simplified URL (fewer styles):
https://fonts.googleapis.com/css2?family=Roboto&display=swapLocal font assets
You can bundle local font files within your theme by using the @font-face rule in your style.scss or style.ts file. You will need to place the font files, such as prefer .woff2, in the following directory:
your-theme/assets/fonts/<FontName>/In your style.scss or style.ts file, define the font family by using the @font-face rule to load the font files:
// style.scss
/* Lato Regular */
@font-face {
font-family: 'Lato';
src: url('./assets/fonts/Lato/Lato-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
/* Lato Italic */
@font-face {
font-family: 'Lato';
src: url('./assets/fonts/Lato/Lato-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
}
...// style.ts
export const CssBaseline = {
root: ({ styleState }) => {
const rootUrl = styleState.rootUrl || ''
return `
/* Lato Regular */
@font-face {
font-family: 'Lato';
src: url('${rootUrl}themes/test/assets/fonts/Lato/Lato-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
/* Lato Italic */
@font-face {
font-family: 'Lato';
src: url('${rootUrl}themes/test/assets/fonts/Lato/Lato-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
}
...
`
}
}2. Register and apply
Add the font name (and URL for hosted fonts) in variables.json so it appears in Theme Settings.
Hosted example:
{
"ref": {
"typeface": {
"customFonts": [
{ "name": "Roboto", "url": "https://fonts.googleapis.com/css2?family=Roboto&display=swap" }
],
"fontFamily": "Roboto"
}
}
}Local example (Lato already loaded via @font-face, no URL needed):
{
"ref": {
"typeface": {
"customFonts": [
{ "name": "Lato" }
],
"fontFamily": "Lato"
}
}
}Apply and verify the font by starting your app:
npm startSome points to consider during your verification process:
- Theme Settings > Typography lists the font.
- If changes do not appear, hard-refresh or clear browser cache to bypass a cached stylesheet.
3. Optimize and accessibility
Here are some best practices to ensure optimal performance and accessibility when using custom fonts:
- Limit weights/styles to what you actually use (e.g., 400, 600).
- Provide a robust fallback stack:
Lato, ".Avenir Next", Arial, sans-serif - Keep
htmlconsistent; avoid shrinking global text unexpectedly.Font Size - Group @font-face declarations together; avoid duplicates.
- Confirm font licensing allows web embedding.
- Include fallback generic family (e.g.,
sans-serif) at the end of the stack. - Avoid listing the same font name multiple times; keep stacks concise.
What's next?
Learn about the different theme development options and how to create and customize themes: