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, how to manually add a second font to your project, and why automated font optimization tools are starting to matter in modern setups.
In this chapter...
Here are the topics we will cover:
𫨠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).

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?
What does font-display help you control?
βοΈ 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.The browser sees a
<link href="https://fonts.googleapis.com/...">tag and requests a stylesheet. - 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:
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:
Just below, add the following body rule:
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
.lusitanautility 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
700weight.- Keep only the files you actually need. Less dead weight, less nonsense.
- Use
woff2files when possible.- Add your
@font-facerules insrc/global.css.- Create a reusable
.lusitanaclass 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.
Once you run the app, you should see Lusitana applied to the paragraph and to the logo 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.
βοΈ Advanced: automatic font optimization with Fontless
The setup you used in this chapter is still a very good way to learn how font loading works. You explicitly declared a font with @font-face, applied it yourself, and saw how fallback fonts help the browser render text before the custom font is ready.
If you want a more automated setup in a real project, Qwik also introduced Fontless, a Vite plugin that detects font-family usage in your CSS, resolves fonts from supported providers, and generates optimized @font-face rules with metric-based fallbacks to reduce layout shifts.
Fontless is interesting for production projects because it automates part of the font optimization work. For learning purposes, though, the manual approach used in this chapter is still better because it shows the mechanics clearly instead of hiding them behind tooling.
In other words: learn the explicit setup first, then use automation when it genuinely saves time. Fancy tooling is nice, but only after you understand the plumbing.
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?
What is a sensible reason to manually host a second font?
Recommended reading
Here are a few solid references if you want to go a bit deeper without drowning in unnecessary theory:
- Qwik Docs | Font optimization cookbook
- Qwik Blog | Effortlessly optimize web fonts with Fontless
- web.dev | Best practices for fonts
Source code
You can find the source code for chapter 6 2026 Edition 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.
Was this helpful?