How to add Fonts in Next.js Using the Font Optimization Feature
- Md. Saad
- September 29, 2024
Introduction
Font optimization is a crucial aspect of web development that focuses on enhancing the performance and visual appeal of web fonts. By implementing various techniques, developers can ensure that fonts load quickly and render smoothly, providing a better user experience. However, these processes are not easy. Thanks to Next.js for its next/font module, which simplifies these hassles for developers.
Next.js for font optimization offers numerous benefits. It includes an automatic font optimization at build time, which improves performance metrics like First Contentful Paint (FCP) and Largest Contentful Paint (LCP). The built-in next/font package allows for self-hosting fonts, reducing latency and enhancing privacy. Next.js also supports the font-display property to prevent layout shifts, and it enables subsetting and the use of variable fonts for better performance. These features collectively enhance SEO and provide a smoother user experience, making Next.js a powerful tool for managing and optimizing web fonts.
Prepare Your Next.js Application
Before setting up the GitHub Actions workflow, the first and foremost step is to create a Next.js App. Use the following command to create a next.js app.
npx create-next-app@latest app-name
As it is not an article on creating the next.js app, we will not discuss it in detail. If you want to read it in detail follow the link.
Steps to Add Google Fonts
Next.js automatically self-hosts Google Fonts. It is also served from the domain where the site is deployed. So no requests are sent to Google by the browser. To get started, import the Google font from next/font/google as a function. For using a variable font, we don't need to specify the font weight. Otherwise, we have to specify weights.
Example of a variable font:
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
)
}
Example of a non-variable font:
import { Roboto } from 'next/font/google'
// If loading a variable font, you don't need to specify the font weight
const roboto= Roboto({
subsets: ['latin'],
display: 'swap',
weight: '400',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={roboto.className}>
<body>{children}</body>
</html>
)
}
For a non-variable font, we can set multiple weights using an array.
import { Roboto } from 'next/font/google'
// If loading a variable font, you don't need to specify the font weight
const roboto= Roboto({
subsets: ['latin'],
display: 'swap',
weight: ['400', '700'],
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={roboto.className}>
<body>{children}</body>
</html>
)
}
Note: We have to use an underscore (_) for font names with multiple words. E.g. Roboto Mono should be imported as Roboto_Mono.
Adding Multiple Font
We can multiple Google fonts also in our Next.js Project. There are two approaches to add multiple fonts in Next Js. Let’s discuss them.
The first method is to write a utility function that imports, exports, and applies a font's className as needed. This guarantees that the font is only loaded whenever it is generated on the site.
- Let’s create app/fonts.js file and inside it add the following codes
import { Inter, Roboto_Mono } from 'next/font/google'
export const inter = Inter({
subsets: ['latin'],
display: 'swap',
})
export const roboto_mono = Roboto_Mono({
subsets: ['latin'],
display: 'swap',
})
- Now in the app/layouts.js import Inter font and use it as a global font
import { inter } from './fonts'
export default function Layout({ children }) {
return (
<html lang="en" className={inter.className}>
<body>
<div>{children}</div>
</body>
</html>
)
}
- Now import Roboto Mono font and use it whenever needed. An example is given for the heading on the tag in the app/page.js file.
import { roboto_mono } from './fonts'
export default function Page() {
return (
<>
<h1 className={roboto_mono.className}>My page</h1>
</>
)
}
Another Method of adding multiple fonts is using CSS Varaible. Let’s Look into an example:
- Like before, add a normal font, add a normal font in the app/layout.js file. Then all we have to do is add a variable in the font function and use that variable as the font className. Here is an example given below:
import { Inter, Roboto_Mono } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
display: 'swap',
})
const roboto_mono = Roboto_Mono({
subsets: ['latin'],
variable: '--font-roboto-mono',
display: 'swap',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
<body>
<h1>My App</h1>
<div>{children}</div>
</body>
</html>
)
}
In this example:
- We have created two variables for Inter and Roboto Mono Font ( '--font-inter','--font-roboto-mono'
- Then use them as className (`${inter.variable} ${roboto_mono.variable}`) . This will create two separate classes using the font variable added at the top.
Now use them in the CSS file as like a CSS variable:
html {
font-family: var(--font-inter);
}
h1 {
font-family: var(--font-roboto-mono);
}
In the example above, Inter will be applied globally, and any <h1> tags will be styled with Roboto Mono.
Use Local Fonts
Instead of using Google font, we can also use Local font in our project.
- To add a local font, we have to use next/font/local. Then we need to specify the src of the font. Here is an example of a variable fonts:
import localFont from 'next/font/local'
// Font files can be colocated inside of `app`
const myFont = localFont({
src: './fonts/my-font.woff2',
display: 'swap',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={myFont.className}>
<body>{children}</body>
</html>
)
}
In this example:
- The localFont utility from Next.js loads font files stored locally in your project.
- Then add the path (./fonts/my-font.woff2) as the src value.
When integrating numerous files for a single font family such as non-variable fonts’ wights, src can be an array:
const roboto = localFont({
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
],
})
Fonts with Tailwind CSS
All the steps are the same for adding fonts for Tailwind CSS. We can use any Google font from next/font/google. Moreover, We can use any font from Google or Local Fonts also. Only the changes we have to do are in the tailwind.config.js.
- Let’s add multiple fonts in the project like before:
import { Inter, Roboto_Mono } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
display: 'swap',
})
const roboto_mono = Roboto_Mono({
subsets: ['latin'],
variable: '--font-roboto-mono',
display: 'swap',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
<body>
<h1>My App</h1>
<div>{children}</div>
</body>
</html>
)
}
- Instead of configuring a CSS file, we will configure the tailwind.config.js file. Read the article to learn more about adding Tailwind CSS in a Next Js project.
- Let’s add a CSS variable in the file like the following example:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
fontFamily: {
sans: ['var(--font-inter)'],
mono: ['var(--font-roboto-mono)'],
},
},
},
plugins: [],
}
- Finally, use the font-sans and font-mono as the className to apply the font to any element.
Conclusion
That's it for you. Here are some cool and amazing ways to use Google and local fonts in a Next JS project. Thus, it will help to create fast, efficient, and visually appealing websites.
I hope you got a lot out of reading this. Please do not hesitate to contact StaticMania with any questions or feedback. Happy coding!