Skip to content

6

Optimizing Fonts
2026 Edition

In the previous chapter, you connected your dashboard pages with Qwik City navigation. Now let's improve the reading experience by working on typography.

In this chapter, you'll see why font loading matters, how to self-host a primary font with Fontsource, and how to manually add a second font to your project.

🫨 Why optimize fonts?

Fonts have a big impact on design, but they also come with a cost. If a custom font loads late, the browser may first render text with a fallback font and then replace it with the real one once it becomes available.

That swap can change the size, spacing, or wrapping of the text. When that happens, nearby elements can move too. That's one of the ways font loading can contribute to Cumulative Layout Shift (CLS).

Mock UI showing a layout shift caused by a late-loading custom font.

A good font setup is not just about looks. It also helps text appear quickly, keeps layout shifts under control, and reduces unnecessary external dependencies.

When a custom font loads, browsers usually follow one of two strategies: FOIT (Flash Of Invisible Text) or FOUT (Flash Of Unstyled Text), as explained in the Qwik font docs.

💡

FOIT hides text until the font is ready, while FOUT shows a fallback font first and swaps it later. Both approaches have drawbacks and can contribute to layout shifts. You can read more about that in web.dev's CLS guide.

A sudden shift in layout makes the user confirm a large order they intended to cancel.

The font-display descriptor lets you control how the browser behaves while a font is loading. For example, swap shows fallback text immediately, while fallback reduces long swap behavior. There is no single perfect value here. It depends on the loading strategy you want.

It’s time to take a quiz!

Test your knowledge and see what you’ve just learned.

Why can custom fonts affect CLS?

You must choose response !

What does font-display help you control?

You must choose response !

⚖️ Google Fonts vs self-hosting

Google Fonts is popular for a reason. It's easy to use, the catalog is huge, and you can get something decent working very quickly.

The downside is that you rely on third-party requests. In practice, that means extra network work, less control over delivery, and another dependency for something as basic as text.

With a hosted Google Fonts setup, the usual flow looks like this:

  1. 1.The browser sees a <link href="https://fonts.googleapis.com/..."> tag and requests a stylesheet.
  2. 2.That stylesheet then points to one or more font files, often served from another domain such as fonts.gstatic.com.

That extra indirection is not catastrophic, but it does mean more moving parts than serving the files yourself.

Why self-host fonts?

Self-hosting means the font files are served as part of your own app instead of being fetched from a third-party provider.

That gives you a few practical benefits:

  • More control over what gets loaded
  • Fewer third-party dependencies
  • Better privacy and caching control
  • A cleaner setup for offline or PWA scenarios

Tiny but important nuance: self-hosting is often a very good choice, but it is not automatically faster in every setup. Server quality, caching, and delivery still matter. The web remains a chaotic little beast.

And if raw performance is your absolute priority, system fonts remain the simplest option because they are already installed on the user's machine, as noted in the Qwik font docs.

📦 Using Fontsource

One very convenient way to self-host fonts is Fontsource.

Fontsource packages open source fonts as npm dependencies, so you don't have to manually hunt down and organize every font file yourself. It still supports the variable Inter package we want to use here: @fontsource-variable/inter.

For this dashboard, let's use the variable version of Inter as the primary font.

🔤 Add a primary font with Fontsource

First, install the package @fontsource-variable/inter:

Terminal

Fontsource also offers a simpler import-based setup. In a Qwik City project, the official Fontsource Qwik guide suggests importing the font in src/routes/layout.tsx, although importing it in index.tsx or another component works too.

For learning purposes, we'll use the more explicit approach here with @font-face in src/global.css. That way, you can clearly see how the font is declared and applied.

In src/global.css, add the following declaration below the Tailwind import:

src/global.css

Just below, add the following body rule:

src/global.css

Using a fallback such as sans-serif is important. If the custom font is not ready yet, the browser still has something sensible to render immediately.

Once that's done, open your browser devtools, inspect the <body> element, and check that the font family is now applied.

Inter font applied to the body element.

🛠️ Practice: add a second font manually

Fontsource is great, but it's not the only path. Sometimes you'll want to host a font manually, either because it's not available in the package you want, or because you prefer to manage the files yourself.

For this practice, you'll add a secondary font called Lusitana.

Your goal is to:

  • download the font files,
  • place them in your project,
  • declare them with @font-face,
  • create a .lusitana utility class,
  • apply that class to the main welcome paragraph on the homepage.

For this exercise, use Google Webfonts Helper. It lets you download optimized font files along with a CSS snippet you can adapt.

Download the two files you need, regular and 700, then place them in a public/fonts/ folder. Qwik's current docs place fonts in public/ as static assets served from the app root, so this is the cleanest teaching path here.

Tips before revealing the solution

Hints:

  • Open Google Webfonts Helper / Lusitana and include the 700 weight.
  • Keep only the files you actually need. Less dead weight, less nonsense.
  • Use woff2 files when possible.
  • Add your @font-face rules in src/global.css.
  • Create a reusable .lusitana class instead of styling a single element directly.

The <LRDQwikLogo /> component also uses Lusitana in this chapter setup, so once everything is wired correctly, you should see the font appear both in the paragraph and in the logo component.

You can download it here:

Add the downloaded LRDQwikLogo.tsx file to your src/assets/svg/ folder, then import it in src/routes/index.tsx and uncomment the <LRDQwikLogo /> component.

src/routes/index.tsx

Once you run the app, you should see Lusitana applied to the paragraph and to the logo component.

Lusitana font applied to the paragraph and the LRDQwikLogo component.

Nice. At this point, your app uses a primary font managed with Fontsource and a secondary font hosted manually. That's a very realistic setup.

It’s time to take a quiz!

Test your knowledge and see what you’ve just learned.

Why is Fontsource a useful option in a Qwik project?

You must choose response !

What is a sensible reason to manually host a second font?

You must choose response !

Here are two solid references if you want to go a bit deeper without drowning in unnecessary theory:

Source code

You can find the source code for chapter 6 on GitHub.

You've Completed Chapter 6

You've learned how to optimize and self-host fonts in your Qwik app.

Next Up

7: Optimizing Images

Next, you'll improve image loading and see how Qwik handles image optimization.