<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MahdiRashidi</title>
    <description>The latest articles on DEV Community by MahdiRashidi (@chief-2001).</description>
    <link>https://dev.to/chief-2001</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1258702%2F7c2e27f1-4784-48f7-bee7-ddc178326fba.png</url>
      <title>DEV Community: MahdiRashidi</title>
      <link>https://dev.to/chief-2001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chief-2001"/>
    <language>en</language>
    <item>
      <title>Web Font Optimization in web applications</title>
      <dc:creator>MahdiRashidi</dc:creator>
      <pubDate>Thu, 12 Nov 2026 10:48:50 +0000</pubDate>
      <link>https://dev.to/chief-2001/web-font-optimization-4ea2</link>
      <guid>https://dev.to/chief-2001/web-font-optimization-4ea2</guid>
      <description>&lt;p&gt;&lt;em&gt;How to reduce font payloads, improve rendering, and use variable fonts in modern web applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fonts are easy to overlook when optimizing a website. We spend time reducing JavaScript bundles, optimizing images, and tuning server responses—but custom typefaces can quietly add hundreds of kilobytes to the page.&lt;/p&gt;

&lt;p&gt;In this guide, we'll walk through four approaches to font optimization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compressing the font files you already use.&lt;/li&gt;
&lt;li&gt;Choosing modern web-font formats such as WOFF2.&lt;/li&gt;
&lt;li&gt;Using built-in font optimization in frameworks such as Next.js 16.&lt;/li&gt;
&lt;li&gt;Switching to variable fonts when the trade-offs make sense.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is not just to ship smaller files. It's to make &lt;strong&gt;text visible sooner, avoid unnecessary downloads, and preserve visual stability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why should we optimize fonts?
&lt;/h2&gt;

&lt;p&gt;A custom web font is a resource the browser has to download before it can display text using that typeface. Depending on how the font is configured, it can cause several performance and usability issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common problems caused by unoptimized fonts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Larger network payloads.&lt;/strong&gt; Downloading separate files for Light, Regular, Medium, SemiBold, Bold, and other weights can add significant transfer costs, especially across multiple scripts or language subsets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flash of Invisible Text (FOIT).&lt;/strong&gt; Some &lt;code&gt;font-display&lt;/code&gt; choices can temporarily hide text while waiting for the web font.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flash of Unstyled Text (FOUT).&lt;/strong&gt; When fallback text is displayed first and later replaced with the web font, users can notice the change in typography.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout shifts (CLS).&lt;/strong&gt; Different glyph widths and font metrics can change line breaks and move surrounding elements when the web font arrives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slower initial rendering on limited networks.&lt;/strong&gt; The effect is especially noticeable when a font used in above-the-fold content is unnecessarily large or delayed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fonts can affect &lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt; when they delay a large text element, and poor metric matching can affect &lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt;. Not every font optimization improves every metric, so always measure your own application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: 535 KB of font requests
&lt;/h3&gt;

&lt;p&gt;Imagine a page downloading seven different font weights when its initial interface really needs just Regular and Bold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fadcq4j6wcc6ak7mwnl17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fadcq4j6wcc6ak7mwnl17.png" alt="Illustrative Chrome DevTools Network view showing seven font files adding up to approximately 535 KB." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Illustrative DevTools mockup—not a real production benchmark. The 535 KB figure is an example.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To check your own application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Chrome DevTools → Network&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Font&lt;/strong&gt; filter.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Disable cache&lt;/strong&gt; and reload the page.&lt;/li&gt;
&lt;li&gt;Check the transferred size, number of requests, and which files actually loaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember: the browser doesn't necessarily download every font you declare in CSS. It generally requests the font faces it needs for rendered text, unless preloading changes that behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Option one: Compress the font files
&lt;/h2&gt;

&lt;p&gt;Compression is one of the easiest places to start because you can often retain the existing font design, weight choices, and styling.&lt;/p&gt;

&lt;p&gt;For example, you can try an online tool such as &lt;a href="https://fontcompressor.com/" rel="noopener noreferrer"&gt;Font Compressor&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step by step
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Back up the originals.&lt;/strong&gt; Keep your source font files unchanged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open a compression tool.&lt;/strong&gt; Visit &lt;a href="https://fontcompressor.com/" rel="noopener noreferrer"&gt;fontcompressor.com&lt;/a&gt; or another reliable font optimization service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload eligible fonts.&lt;/strong&gt; Check that the font's license permits processing and that you're comfortable uploading it to a third party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose supported optimization options.&lt;/strong&gt; These might include compression, conversion, or subsetting; available features depend on the tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download and compare.&lt;/strong&gt; Compare file sizes, glyph coverage, and the appearance of representative text at every required weight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure in DevTools again.&lt;/strong&gt; Compare transfer sizes using the same test conditions.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Removing glyphs can reduce file size, but careless subsetting can break your UI. For multilingual apps, test Persian, Arabic, accented Latin characters, numerals, punctuation, and combining marks. For example, verify both &lt;code&gt;آ&lt;/code&gt; and &lt;code&gt;ا&lt;/code&gt; if your application renders Persian.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also use local font tooling when you don't want to upload licensed or private assets to an external service.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Option two: Use WOFF2 instead of legacy TTF
&lt;/h2&gt;

&lt;p&gt;The font format also affects transfer size.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;General recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TTF / OTF&lt;/td&gt;
&lt;td&gt;Common desktop/source font formats&lt;/td&gt;
&lt;td&gt;Keep when needed as source files; not usually the best web delivery format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WOFF&lt;/td&gt;
&lt;td&gt;Web font container with compression&lt;/td&gt;
&lt;td&gt;Useful mainly for older compatibility requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WOFF2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modern, efficiently compressed web font format&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Preferred for modern browsers&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;WOFF2 generally compresses better than WOFF and uncompressed TTF/OTF. The exact improvement depends on the font and how it was originally encoded.&lt;/p&gt;

&lt;p&gt;Here's a basic CSS example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Brand"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/fonts/Brand-Regular.woff2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"woff2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Brand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;WOFF2 conversion is not the same as creating a variable font.&lt;/strong&gt; Converting to WOFF2 changes how the font is packaged and compressed for the web; a variable font encodes a range of design variations in a font with variation axes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Option three: Use a framework's font optimizer
&lt;/h2&gt;

&lt;p&gt;Modern JavaScript frameworks can automate several parts of font delivery: generating font-face declarations, self-hosting, providing CSS class names or variables, and emitting preload hints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js:&lt;/strong&gt; provides &lt;code&gt;next/font&lt;/code&gt;, including &lt;code&gt;next/font/local&lt;/code&gt; for local files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nuxt:&lt;/strong&gt; offers font optimization through its ecosystem, including Nuxt Fonts, with configuration that differs from Next.js.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll focus on &lt;strong&gt;Next.js 16.x with the App Router&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Prepare your fonts
&lt;/h3&gt;

&lt;p&gt;Place the WOFF2 font files alongside your font declaration module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  fonts/
    Brand-Light.woff2
    Brand-Regular.woff2
    Brand-Medium.woff2
    Brand-Bold.woff2
  fonts.ts
  layout.tsx
  globals.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Configure &lt;code&gt;next/font/local&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;app/fonts.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;localFont&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"next/font/local"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;brandFont&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"./fonts/Brand-Light.woff2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"300"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"./fonts/Brand-Regular.woff2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"400"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"./fonts/Brand-Medium.woff2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"./fonts/Brand-Bold.woff2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"700"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Arial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sans-serif"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;adjustFontFallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Arial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"--font-brand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;src&lt;/code&gt; paths are relative to &lt;code&gt;app/fonts.ts&lt;/code&gt;, where you call &lt;code&gt;localFont&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Register the font in the root layout
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;app/layout.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;brandFont&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"./fonts"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s2"&gt;"./globals.css"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;brandFont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Use your CSS font variable
&lt;/h3&gt;

&lt;p&gt;Because the generated custom property is applied to &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; in the layout above, apply the &lt;code&gt;font-family&lt;/code&gt; on &lt;strong&gt;body&lt;/strong&gt; as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--font-brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't need to reference a CSS variable, you can apply &lt;code&gt;brandFont.className&lt;/code&gt; directly to your element instead.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzbn6g3ewef69oqkxo0jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzbn6g3ewef69oqkxo0jp.png" alt="Illustrated Next.js 16 localFont configuration, including swap and fallback settings." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Visual summary of the local font definition. Use the code blocks above as the implementation reference.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the &lt;code&gt;display&lt;/code&gt; option
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;display&lt;/code&gt; controls CSS &lt;code&gt;font-display&lt;/code&gt;: what a browser shows while a web font is being loaded and whether the fallback text can be swapped later.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;th&gt;Trade-off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;auto&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Browser chooses the strategy&lt;/td&gt;
&lt;td&gt;Behavior is browser-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;block&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Has a temporary invisible-text period, then can show fallback until the font loads&lt;/td&gt;
&lt;td&gt;May delay readable text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;swap&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fallback displays immediately and is swapped once the web font loads&lt;/td&gt;
&lt;td&gt;Readable text early, but possible visible reflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fallback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Very brief block period followed by a limited swap period&lt;/td&gt;
&lt;td&gt;May retain fallback if the font loads too late&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;optional&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Very brief block period; a late font may not replace fallback&lt;/td&gt;
&lt;td&gt;Prioritizes stability over guaranteed custom-font appearance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following timeline illustrates these strategies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg199ykcgsypzudq7dse8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg199ykcgsypzudq7dse8.png" alt="Font-display timing diagram comparing block, swap, fallback, and optional with invisible, fallback, and webfont states." width="739" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Font-display timing illustration supplied for this article. The approximately 100 ms and 3 s windows are conceptual/spec-recommended examples, not fixed timings in every browser.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which value should you choose?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For text-heavy applications, &lt;code&gt;swap&lt;/code&gt; is a useful starting point because text stays visible. But if replacing the fallback font produces distracting layout shifts, investigate metric adjustments or test &lt;code&gt;optional&lt;/code&gt;. There's no universal winner for every interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding &lt;code&gt;fallback&lt;/code&gt;, &lt;code&gt;adjustFontFallback&lt;/code&gt;, and &lt;code&gt;preload&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;These Next.js options solve related but different problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fallback&lt;/code&gt;&lt;/strong&gt; sets an ordered list of fallback font families. For example, &lt;code&gt;['Arial', 'sans-serif']&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;adjustFontFallback&lt;/code&gt;&lt;/strong&gt; asks Next.js to generate metric-adjusted fallback styles to reduce layout shift. With &lt;code&gt;next/font/local&lt;/code&gt;, the supported options include &lt;code&gt;'Arial'&lt;/code&gt;, &lt;code&gt;'Times New Roman'&lt;/code&gt;, or &lt;code&gt;false&lt;/code&gt;; the default is &lt;code&gt;'Arial'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;preload&lt;/code&gt;&lt;/strong&gt; tells Next.js whether to emit preload hints. The default is &lt;code&gt;true&lt;/code&gt;. Be careful when declaring many static files: preloading fonts that are not needed early can compete with other important resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;variable&lt;/code&gt;&lt;/strong&gt; exposes the generated font family through a CSS variable such as &lt;code&gt;--font-brand&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;next/font/local&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; combine multiple static weight files into a genuine variable font. It automates loading and application; the source files stay separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Advanced: Variable fonts
&lt;/h2&gt;

&lt;p&gt;A traditional &lt;strong&gt;static&lt;/strong&gt; font file often stores a single instance of a typeface: one weight such as 400 (Regular) or 700 (Bold), for example.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;variable font&lt;/strong&gt; can represent a range of styles using one font file and one or more axes. These may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;wght&lt;/code&gt;: weight, such as 100–900.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wdth&lt;/code&gt;: width, if supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;opsz&lt;/code&gt;: optical size, if supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slnt&lt;/code&gt;: slant, if supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means a single variable WOFF2 file may cover weights such as 300, 400, 500, 600, and 700 without requiring a separate file for each weight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why can variable fonts help?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer font requests&lt;/strong&gt; when an app actually uses several static weights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous weight values&lt;/strong&gt; for richer typography and animation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simpler asset management&lt;/strong&gt; with one variable source instead of many individual files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, &lt;strong&gt;one variable font is not automatically smaller&lt;/strong&gt; than a couple of well-subsetted static files. If you only use Regular and Bold, the combined size of two static WOFF2 files may be better. Benchmark both strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you create a variable font from static font files?
&lt;/h3&gt;

&lt;p&gt;Not automatically. Renaming several static files, merging them into an archive, or converting them into WOFF2 does not make a true variable font.&lt;/p&gt;

&lt;p&gt;A proper variable font requires compatible outlines/master designs, interpolation data, and valid variation tables. If the masters differ in contour structure or glyph coverage, the resulting font can render incorrectly—especially for complex scripts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best practice:&lt;/strong&gt; Use an official variable font from the font publisher whenever possible, and verify licensing and supported axes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Obtain a real variable WOFF2 font
&lt;/h3&gt;

&lt;p&gt;In this example, assume your file named &lt;code&gt;BrandVariable.woff2&lt;/code&gt; genuinely supports a weight range from &lt;strong&gt;100 to 900&lt;/strong&gt;. Don't claim a range the font doesn't actually contain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure it with &lt;code&gt;next/font/local&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;app/fonts.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;localFont&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"next/font/local"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;brandVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;localFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"./fonts/BrandVariable.woff2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"100 900"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Arial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sans-serif"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;adjustFontFallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Arial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"--font-brand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Apply the variable font
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;app/layout.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;brandVariable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"./fonts"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s2"&gt;"./globals.css"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;brandVariable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Use different weights in CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--font-brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;small&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fda3f97g8q3jm09ztdy88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fda3f97g8q3jm09ztdy88.png" alt="Diagram comparing multiple static font weights with one variable WOFF2 file and a Next.js localFont definition." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual comparison of static and variable fonts. The diagram illustrates fewer files, not a guaranteed reduction in total transferred bytes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A variable font that covers a weight range does not automatically provide an italic font. If your design needs italic, check whether your font actually supports that style or add the correct italic face separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Verify your optimization
&lt;/h2&gt;

&lt;p&gt;Do not judge an optimization just by looking at the files in your repository. Compare production behavior with the same browser and network settings.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build and run the production application (&lt;code&gt;next build&lt;/code&gt;, followed by &lt;code&gt;next start&lt;/code&gt; if appropriate for your deployment).&lt;/li&gt;
&lt;li&gt;Open DevTools → &lt;strong&gt;Network → Font&lt;/strong&gt; and test with a cold cache.&lt;/li&gt;
&lt;li&gt;Record &lt;strong&gt;request count&lt;/strong&gt; and &lt;strong&gt;transferred bytes&lt;/strong&gt;, not just the sizes of source files.&lt;/li&gt;
&lt;li&gt;Check which fonts are preloaded but not immediately used.&lt;/li&gt;
&lt;li&gt;Throttle the connection and watch for FOIT, FOUT, and layout movement.&lt;/li&gt;
&lt;li&gt;Review LCP and CLS with Lighthouse or a performance recording.&lt;/li&gt;
&lt;li&gt;Check glyph coverage and line breaks for every language you support.&lt;/li&gt;
&lt;li&gt;Compare both first and repeat visits to understand caching.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's useful to record a before/after table from your real application:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Font requests&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Font bytes transferred&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LCP&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLS&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Don't publish an improvement percentage unless you've measured it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Typography is part of your application's performance budget. Large font files, unnecessary font weights, unoptimized formats, and poor fallback choices can all make an otherwise fast application feel slower.&lt;/p&gt;

&lt;p&gt;Start with straightforward improvements: &lt;strong&gt;audit requests, compress carefully, use WOFF2, and load only the weights you actually need&lt;/strong&gt;. Frameworks such as Next.js 16 make local font loading easier to manage, and &lt;code&gt;font-display&lt;/code&gt; lets you choose the right rendering trade-off for your interface.&lt;/p&gt;

&lt;p&gt;Then consider &lt;strong&gt;variable fonts&lt;/strong&gt; as an advanced technique when your design uses multiple weights or variation axes—and when real measurements show a benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure first. Optimize deliberately. Verify with real text and real users.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/getting-started/fonts" rel="noopener noreferrer"&gt;Next.js font optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/components/font" rel="noopener noreferrer"&gt;Next.js &lt;code&gt;next/font&lt;/code&gt; API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display" rel="noopener noreferrer"&gt;MDN: &lt;code&gt;font-display&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/learn/performance/optimize-web-fonts" rel="noopener noreferrer"&gt;web.dev: Optimize web fonts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fontcompressor.com/" rel="noopener noreferrer"&gt;Font Compressor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Editor's note: the example Network image is a mockup, not an actual DevTools performance result. Replace it with a screenshot from your own application if you want to present a genuine before/after case study.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>performance</category>
      <category>nextjs</category>
      <category>css</category>
    </item>
  </channel>
</rss>
