DEV Community

Cover image for How to Add Custom Fonts in Next.js and Tailwind CSS Templates
Cruip
Cruip

Posted on • Originally published at cruip.com

How to Add Custom Fonts in Next.js and Tailwind CSS Templates

Since the launch of Cruip, thousands of developers have purchased our templates, and many of them have asked us for assistance to personalize them according to their needs.

We love helping our customers achieve the best possible outcome with our products, but since we are a small team of two and our customer base continues to grow (thankfully), we decided to start a series of articles/guides based on your most common customization questions. This way, we hope to optimize some of our time (that we can invest in creating more products) and offer an even better service to you!

Let’s start with a guide on how to customise the fonts of Tailwind CSS templates built with Next.js. Step by step, we’ll walk you through font management and show you how to create custom versions of the templates that will make them truly one-of-a-kind.

As you may know, the React versions of Cruip templates are built with Tailwind CSS and use Next.js 13’s new app directory (App Router). Additionally, at the time of writing, all templates use Google Fonts and, in some cases, local fonts. Therefore, we’ll illustrate how to add a new Google font, replace the current one, use local fonts, and even utilize system fonts to optimize your website’s performance.

How we use fonts in Cruip templates

Before diving into practical examples, let’s first take a brief overview of how we use fonts in Cruip templates. In general, we define the main font-family on the body tag. In cases where we also use a secondary font, we directly define it on each element using Tailwind CSS classes.

Take our Tidy template, for example. The base font is Inter, defined on the body tag with the font-inter class. For headings, however, we use the serif font Playfair Display, which is defined on each element (h1, h2, and h3) using the font-playfair-display class.

Now, someone might object and ask why we didn’t define the font for headings directly in CSS to avoid repeating it for each element. It would have been a sensible choice, indeed, but we preferred to embrace the philosophy of Tailwind CSS, which encourages the use of classes to define element styles. Moreover, this way, it’s easy to switch to a different font for headings by simply modifying the class.

Adding a new Google Font to a template

Let’s say we want to add a third font for specific parts of the template, and that font is Nothing You Could Do. First, we need to load the font using next/font. Normally, we use the main layout.tsx file for this. However, if we know that we’ll only need this font in a specific component, it’s good practice to load it directly in that component. This way, we avoid loading unnecessary fonts throughout the entire website.

To use the font across all pages, let’s add the following code to the layout.tsx file:

  import { Nothing_You_Could_Do } from 'next/font/google'
Enter fullscreen mode Exit fullscreen mode

With the code above, we imported the font Nothing You Could Do. Keep in mind that for Google Fonts with multiple words in their names, it’s necessary to replace spaces with underscores, and each word should start with a capital letter. In this case, the font is called “Nothing You Could Do”, so we need to use Nothing_You_Could_Do to import it. If you’re unsure about the font name, you can always check the exports in next/font/google within the node_modules folder.

Now let’s define a variable for the font:

  const nycd = Nothing_You_Could_Do({
    subsets: ['latin'],
    variable: '--font-nycd',
    weight: '400',
    display: 'swap'
  })
Enter fullscreen mode Exit fullscreen mode

The variable name is arbitrary but should be consistent with what we’ll define in the Tailwind CSS configuration file.

Next, let’s add the variable to the container element where we want to use the font, which in this case is the body element:

  <body className={`${inter.variable} ${playfair.variable} ${nycd.variable} font-inter antialiased bg-white text-slate-800 tracking-tight`}>
Enter fullscreen mode Exit fullscreen mode

Finally, we need to add the font to the Tailwind CSS configuration file. To do this, open the tailwind.config.js file and add the font-nycd variable to our theme:

  fontFamily: {
    inter: ['var(--font-inter)', 'sans-serif'],
    'playfair-display': ['var(--font-playfair-display)', 'serif'],
    'nycd': ['var(--font-nycd)', 'cursive'],
  }
Enter fullscreen mode Exit fullscreen mode

Great! Now we can use the font on any HTML element by simply adding the font-nycd class, for example:

  <p className="font-nycd">Hello world!</h1>
Enter fullscreen mode Exit fullscreen mode

Replacing one Google Font with another

Let’s stick with the Tidy template and suppose we want to replace the Playfair Display font used for headings with the font Poppins.

First, in the layout.tsx file, we’ll modify the font import. So this line:

  import { Inter, Playfair_Display } from 'next/font/google'
Enter fullscreen mode Exit fullscreen mode

becomes this:

  import { Inter, Poppins } from 'next/font/google'
Enter fullscreen mode Exit fullscreen mode

Next, we’ll remove this code block:

  const playfair = Playfair_Display({
    subsets: ['latin'],
    variable: '--font-playfair-display',
    display: 'swap'
  })
Enter fullscreen mode Exit fullscreen mode

and replace it with this:

  const poppins = Poppins({
    subsets: ['latin'],
    variable: '--font-poppins',
    display: 'swap'
  })
Enter fullscreen mode Exit fullscreen mode

Finally, in the layout.tsx file, we’ll replace the playfair variable with poppins. So this line:

  <body className={`${inter.variable} ${playfair.variable} font-inter antialiased bg-white text-slate-800 tracking-tight`}>
Enter fullscreen mode Exit fullscreen mode

becomes this:

  <body className={`${inter.variable} ${poppins.variable} font-inter antialiased bg-white text-slate-800 tracking-tight`}>
Enter fullscreen mode Exit fullscreen mode

Now, let’s edit the tailwind.config.js file and replace the fonts there as well. So this code block:

  fontFamily: {
    inter: ['var(--font-inter)', 'sans-serif'],
    'playfair-display': ['var(--font-playfair-display)', 'serif'],
  },
Enter fullscreen mode Exit fullscreen mode

changes to this:

  fontFamily: {
    inter: ['var(--font-inter)', 'sans-serif'],
    poppins: ['var(--font-poppins)', 'sans-serif'],
  },
Enter fullscreen mode Exit fullscreen mode

The final step is to use the right class for the Poppins font on each heading tag. To do this quickly and accurately, we can do a global search for the string “font-playfair-display” and use the “Replace all” function to replace it with “font-poppins”. This way, we’ll replace all instances of font-playfair-display with font-poppins. Usually, all editors (we use VS Code) have a feature to search for a string in specific files. Since we want to make the replacement only in .tsx files, we can specify *.tsx in the “files to include” field.

Using a local font

To add a touch of uniqueness to our template design, we’ve used some fonts that are not available in the Google Fonts library, such as Aspekta, or Cabinet Grotesk.

These fonts are available in .woff2 format and can be easily included in any other Next.js template. Let’s jump into a practical example right away.

Suppose we want to use the bold version of the Aspekta font for the headings in the Tidy template. We’ll download the font from the Github repository and include the file Aspekta-700.woff2 in the public/fonts folder of our project.

Next, we import the font into the layout.tsx file like this:

  import localFont from 'next/font/local'
  const aspekta = localFont({
    src: [
      {
        path: '../public/fonts/Aspekta-700.woff2',
        weight: '700',
      },       
    ],
    variable: '--font-aspekta',
    display: 'swap',  
  })
Enter fullscreen mode Exit fullscreen mode

Let’s add the variable aspekta to the classes of the body element:

  <body className={`${inter.variable} ${aspekta.variable} ${nycd.variable} font-inter antialiased bg-white text-slate-800 tracking-tight`}>
Enter fullscreen mode Exit fullscreen mode

At this point, let’s modify the tailwind.config.js file like this:

  fontFamily: {
    inter: ['var(--font-inter)', 'sans-serif'],
    'aspekta': ['var(--font-aspekta)', 'sans-serif'],
  }
Enter fullscreen mode Exit fullscreen mode

Finally, to use the new font for the headings, we need to replace the class font-playfair-display with font-aspekta on each heading tag. Once again, we’ll do a global search for the string “font-playfair-display” and use the “Replace all” function to replace it with “font-aspekta”.

Using a system font

In this last step of the guide, we’ll explain how and when to use a system font for your Next.js website.

Although Next.js 13 ensures optimal font loading management, avoiding Cumulative Layout Shift (CLS) issues, using system fonts offers additional advantages in terms of performance and site loading speed. Since these fonts are already installed in the operating system or device, they don’t require any additional downloads like Google Fonts or local fonts.

Furthermore, using a system font ensures that the text appearance is consistent with the rest of the operating system or device. This is certainly an advantage, but it can also be a limitation since the system font may not align with your website’s design. In other words, you may not have full control over the typography design of your site.

Another factor to consider is that system fonts may not support specific special characters or symbols you may want to use. In such cases, you may need to resort to external or local fonts.

Ultimately, if custom text design is not a priority and the main goal is to ensure good readability and consistent presentation, using a system font can be a practical choice. There are many popular websites using system fonts, from GitHub to Booking, from Wikipedia to Medium, so you’ll be in good company!

For further insights, we recommend reading this excellent article.

Using system fonts is extremely simple: no font import is necessary! So, let’s assume we want to use only system fonts in Tidy. To do this, we’ll remove the following code blocks from the layout.tsx file:

  import { Inter, Playfair_Display } from 'next/font/google'
  const inter = Inter({
    subsets: ['latin'],
    variable: '--font-inter',
    display: 'swap'
  })
  const playfair = Playfair_Display({
    subsets: ['latin'],
    variable: '--font-playfair-display',
    display: 'swap'
  })
Enter fullscreen mode Exit fullscreen mode

Let’s also remove the inter and playfair variables from the classes of the body element, as well as the font-inter class:

  <body className={`antialiased bg-white text-slate-800 tracking-tight`}>
Enter fullscreen mode Exit fullscreen mode

Next, in the tailwind.config.js file, we can safely remove the entire object that defines the font families in use:

  fontFamily: {
    inter: ['var(--font-inter)', 'sans-serif'],
    'playfair-display': ['var(--font-playfair-display)', 'serif'],
  },
Enter fullscreen mode Exit fullscreen mode

Finally, using a global search, we’ll remove all the now unnecessary classes defined as “font-playfair-display”.

After completing these steps, we suggest testing the typography of your website on different devices and operating systems to ensure that the text design meets your expectations.

Conclusions

Choosing the right font can significantly impact the overall user experience and convey the intended message effectively. Whether you opt for Google Fonts, local fonts, or system fonts, each option has its own advantages and considerations.

We hope that this guide has been helpful in showing you how to customize our Tailwind CSS templates. Happy coding!

Top comments (0)