Lesson 44 of 81
One font file can cover an entire weight and style range instead of shipping a separate static file per weight — the font loader lesson only tells you not to fetch; this one is about not fetching too many times.
10 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A classic web font setup loads a separate file per weight: regular, medium, semibold, bold — four network requests for four points on what is, physically, one continuous design. A variable font collapses that into a single file that encodes the entire weight (and often width, slant) range as an interpolatable axis. font-weight: 450 isn't rounded to the nearest static cut anymore — the browser renders it directly, because the font file actually contains that value.
Most modern Google Fonts — Inter among them — ship as variable by default. That matters for next/font/google specifically: when a font is variable, the weight option becomes optional, because there's no fixed set of weights to choose from anymore. Passing weight: ["400", "700"] to a variable font doesn't make it load faster — it typically does nothing, since the whole point of a variable file is that every weight in between is already there for free.
// app/fonts.ts
import { Inter } from "next/font/google";
// No `weight` option — Inter's default axes cover the full range.
// One file serves font-weight: 400 through 700 (and anything between).
export const inter = Inter({
subsets: ["latin"],
display: "swap",
variable: "--font-inter",
});
/* app/globals.css */
.hero-title {
font-weight: 750; /* not on the standard 100-900 step scale — a static font would round this to 700 or 800 */
}
// A non-variable font, by contrast, must declare every weight it needs up front
import { Roboto_Slab } from "next/font/google";
export const robotoSlab = Roboto_Slab({
subsets: ["latin"],
weight: ["400", "700"], // Roboto Slab ships as static cuts — this is a required option, not optional
variable: "--font-roboto-slab",
});
Inter(...) resolves to a single @font-face covering the whole weight axis, so font-weight: 750 in CSS renders as an actual interpolated 750, not a browser-side fake-bold synthesis of 700. Roboto_Slab, ships as discrete static files, so weight is required — omitting it is a build-time error, because there's no "whole range" to fall back to; the loader needs to know exactly which files to fetch.
next/font doesn't convert a static font into a variable one — it just does or doesn't require weight depending on what the underlying file actually is. If a font is only distributed as static cuts, no next/font option makes intermediate weights render smoothly.font-weight values between the named steps (100/200/.../900) only render smoothly on a variable font. On a static font, an in-between value like 620 silently snaps to the nearest weight that was actually loaded — not an error, just not what the CSS asked for.next/font/local variable-font support depends on the font file itself, not on Next.js. Point next/font/local at a genuine variable .woff2 (one that declares a weight axis) and the same "no weight option needed" behavior applies; point it at a static file and weight is required exactly as with a non-variable Google Font.This builds directly on the general next/font lesson — same build-time self-hosting, same layout-shift-free fallback mechanics. The difference here is just which axis of a font file you're optimizing: not "does the browser have to fetch it," but "how many separate files does a full weight range cost," which is a font-format question that next/font surfaces rather than solves outright.