Repository navigation
how to preload only some font weights with next/font
#99025
Summaryi want to preload font-weight 400 of a local font, but not preload additional font-weights, using the only hint i found was this comment, which relies on behavior that is not documented and hard to discover (and the Additional informationNo response ExampleNo response |
Replies: 10 comments 8 replies
|
const bodyFont = localFont({ src: './MyFont-Regular.woff2', weight: '400', variable: '--font-body' })
const boldFont = localFont({ src: './MyFont-Bold.woff2', weight: '700', preload: false, variable: '--font-bold' })The docs are explicit that each call is its own hosted instance, which is what makes the preload decision independent. The catch is the one you already found: two calls mean two families, so weight-based selection inside one family is what needs the |
|
@stefanprobst Cedric is spot on— If you want to avoid manually overriding 1. Define the fonts separately in your
|
|
Hi @stefanprobst thanks for the call out, I'll investigate a bit more, get some agents to poke around some apps, and do the necessary docs updates, but I think there might be a feature gap still. I think #69900 tried to address that no? As far as I can tell the other answers are non-starters right? |
|
I think the feature gap is real here.
localFont({
src: [
{ path: './Regular.woff2', weight: '400', preload: true },
{ path: './Bold.woff2', weight: '700', preload: false },
],
})Splitting the weights into two The So for the specific requirement of one font family + one CSS variable + different preload behavior per weight, I don't think there is currently a clean, documented next/font solution. This is essentially the use case discussed in #46699, which proposes selective preload per local font source. I'd keep an eye on #69900 as well, since it appears related to this gap. References: |
|
Currently preload is set per localFont() call, not per weight inside a single call, and there is no official documented way to keep one font-family plus one CSS variable while preloading only some weights. The cleanest supported approach is two separate localFont calls: one for the regular weight with preload true and one for the bold weight with preload false, each exporting its own CSS variable. Apply both variables on the root html element and then map them in CSS or Tailwind so body uses the regular variable and .font-bold / strong / b use the bold variable. This keeps the preload behavior explicit and avoids fragile undocumented hacks. There is still a real feature gap here (also discussed in #46699); until Next.js adds a proper API for selective preloading per weight, the two-call pattern is the least brittle option. |
|
I found PR #69900, which proposes preload per font source inside src[]. That seems closely related to this use case. Since the PR is still open, has anyone tested whether this approach is still being considered or whether there is a newer supported API? |
|
To control preloading for specific font weights using
Here is the recommended setup: import localFont from 'next/font/local';
export const mainFont400 = localFont({
src: './fonts/my-font-400.woff2',
weight: '400',
preload: true,
variable: '--font-main-400',
});
export const mainFont700 = localFont({
src: './fonts/my-font-700.woff2',
weight: '700',
preload: false,
variable: '--font-main-700',
});
Then apply both CSS variables to your `<html>` or `<body>` element so both weights are accessible while only preloading the primary one
```tsx
<html className={`${mainFont400.variable} ${mainFont700.variable}`}>
|
|
To preload only specific weights (e.g., 400) while loading additional weights (e.g., 700) on demand without preloading, you can define separate font instances using // app/fonts.ts
import localFont from 'next/font/local';
// 1. Regular font - preloaded by default
export const fontRegular = localFont({
src: './fonts/CustomFont-Regular.woff2',
weight: '400',
preload: true,
variable: '--font-regular',
display: 'swap',
});
// 2. Bold font - preloading disabled
export const fontBold = localFont({
src: './fonts/CustomFont-Bold.woff2',
weight: '700',
preload: false,
variable: '--font-bold',
display: 'swap',
});In your root layout: import { fontRegular, fontBold } from './fonts';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${fontRegular.variable} ${fontBold.variable}`}>
<body>{children}</body>
</html>
);
}By separating the definitions, Next.js will only inject Hope this helps! If this resolves your question, please feel free to mark this as the accepted answer. |
|
I wouldn't rely on that comment. In current What I do is split the critical weight from the rest: const inter400 = localFont({ src: '../fonts/inter-400.woff2', variable: '--font-inter' })
const interRest = localFont({
src: [
{ path: '../fonts/inter-500.woff2', weight: '500' }
{ path: '../fonts/inter-700.woff2', weight: '700' }
]
preload: false
})Use — |
|
A workaround is to split the regular font face into its own // fonts.ts
import localFont from "next/font/local";
export const myFont = localFont({
src: "./fonts/myfont-regular.woff2",
variable: "--font-myfont",
preload: true,
declarations: [{ prop: "font-family", value: "MyFont" }],
});
export const myFontOtherWeights = localFont({
src: [
{ path: "./fonts/myfont-medium.woff2", weight: "500" },
{ path: "./fonts/myfont-bold.woff2", weight: "700" },
],
variable: "--font-myfont-other",
preload: false,
adjustFontFallback: false,
declarations: [{ prop: "font-family", value: "MyFont" }],
});Apply both generated variable classes in the root layout: <html
className={`${myFont.variable} ${myFontOtherWeights.variable}`}
>Because both calls declare the same This appears to work with Next.js 16.2.11 and Turbopack, as reported in this discussion, but I would verify the generated CSS and preload links for the specific Next.js version in use. A native per-source |
Been trying this out, I don't really feel comfortable documenting the pattern — as far as I can see, indeed,
declarationsdoes the trick: