Custom fonts make your site stand out, but poorly optimized fonts hurt your Core Web Vitals.
For best performance, self-host custom fonts on your Remix Server.
Third-Party Fonts
Preconnect to third-party domain to improve fetch time when using services like Google Fonts.
// app/root.tsx
export
const
links
:
LinksFunction
=
(
)
=>
{
return
[
{
rel
:
"preconnect"
,
href
:
"https://fonts.gstatic.com"
,
crossOrigin
:
"anonymous"
}
,
]
}
The crossOrigin attribute is necessary when loading third-party fonts. See Michael Crenshaw article for details.
Self-Hosting Fonts
Every byte counts, use a web font tool like Font Squirrel to minimize font size:
For a deep-dive on creating web fonts, see Creating Font Subsets by Markos Konstantopoulos:
Font Size Comparison
Unblock Render with Font Swap
WebPageTest Performance Report
When fonts are loaded with default display settings, like font-display="block", browsers will hide text entirely for several seconds instead of showing text with a fallback font.
To avoid this behavior, always add font-display: swap to fallback to system fonts:
// styles/fonts.css
@font-face
{
font
-
family
:
"Qualy"
;
src
:
url
(
"/fonts/Qualy.otf"
)
;
font
-
style
:
normal
;
font
-
display
:
swap
;
}
Eliminating CLS from Fonts
You may notice a Cumulative Layout Shift (CLS) penalty after adding font-display: swap.
This happens because some elements may resize as custom fonts streamed in, and can be avoided by providing metric overrides for the fallback fonts:
// styles/fonts.css
@font-face
{
font
-
family
:
"Qualy Override"
;
font
-
style
:
normal
;
font
-
weight
:
400
;
src
:
local
(
"Helvetica Neue"
)
,
local
(
"BlinkMacSystemFont"
)
,
local
(
"Arial"
)
,
local
(
"Noto Sans"
)
,
local
(
"Segoe UI"
)
,
local
(
"Roboto"
)
,
local
(
-
apple
-
system
)
,
local
(
sans
-
serif
)
,
local
(
ui
-
sans
-
serif
)
;
ascent
-
override
:
84.57
%
;
descent
-
override
:
27.27
%
;
line
-
gap
-
override
:
0.00
%
;
size
-
adjust
:
115.30
%
;
}
Add the override to the font family. The syntax for this step may differ depending on your styling framework.
On Nalu, we add them to our TailwindCSS theme:
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module
.
exports
=
{
theme
:
{
extend
:
{
fontFamily
:
{
logo
:
[
"Qualy"
,
"Qualy Override"
]
,
body
:
[
"NunitoSans"
,
"NunitoSans Override"
]
,
}
,
}
,
}
;
Calculating Font Metric Override
Calculating font metric override is a bit of an involved process, check out Simon Hearne article for the nitty-gritty details:
Luckily, we can skip all the math with a simple command, thanks to the Pixel Point team!
npx
fontpie
.
/
qualy
-
regular
.
woff2
Further Reading
The next series of Remix articles will cover our favorite Remix UI Patterns used on Nalu!
Nalu is a wiki engine built on Remix and MDX.
Nalu