Having trouble importing Google Fonts using Styled Components and Next.js?

I encountered an issue while attempting to load Google Fonts. I came across a solution that suggests adding the following code snippet in _document.js to import it within a head tag:

import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          <link
            rel="preload"
            href="/fonts/noto-sans-v9-latin-regular.woff2"
            as="font"
            crossOrigin=""
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
export default MyDocument;

However, this approach conflicted with the code required to enable Styled Components in Next.js:

import Document, { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

Therefore, my query is: how can I adjust my _document.js file to incorporate the styles from Google Fonts?

Additionally, here is the GlobalStyle I am utilizing which does not include the imported fonts:

import { createGlobalStyle } from '@xstyled/styled-components';

const GlobalStyle = createGlobalStyle`

@import url('https://fonts.googleapis.com/css2?family=Lato&family=Rubik&display=swap');

* {
    margin: 0;
    padding: 0;
}

*,
*::before,
*::after {
    box-sizing: inherit;
}

html {
    box-sizing: border-box;
    font-size: 62.5%; 
    position: relative;
    background: grey;
}

body {
  font-family: 'Lato', sans-serif;
}
`;

const BasicLayout = ({ children }: { children: any }) => {
  return (
    <>
      <GlobalStyle />
      {children}
    </>
  );
};

export default BasicLayout;

Answer №1

Visit this webpage for more information:

https://nextjs.org/docs/advanced-features/custom-app

Familiarize yourself with the concept of custom _app.js and then proceed as outlined below:

To begin, craft a personalized _app.js for your application. (This file should be located in the root of your pages directory)

Subsequently, generate a _app.css within the same folder

Afterwards, import the css file into your _app.js

import "./_app.css";

In your _app.css file, include your chosen Google font using the following syntax:

@import url("https://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700&display=swap");

Within the css file and inside the body tag, incorporate the following line:

body {
  font-family: "PT Sans Narrow", sans-serif;
  etc..
}

Answer №2

Encountering the same issue led me to explore a different solution from Hooman's answer, which involved creating a standalone .css file solely for importing Google fonts.

Here is an alternative method for loading fonts while utilizing styled-components:

import Document, {
  Html,
  Head,
  Main,
  NextScript,
  DocumentContext,
  DocumentInitialProps,
} from "next/document";
import { ServerStyleSheet } from "styled-components";

class MyDocument extends Document {
  // Ensure styles are loaded before rendering
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          {/* Google Fonts */}
          <link rel="preconnect" href="https://fonts.googleapis.com" />
          <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
          <link
            href="https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@400;500&display=swap"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Ensure that your render method is not marked as static.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The call to the hooks is not valid. Hooks must be called within the body of a functional component

Could you please take a moment to review the validate method within the elfe-if condition in the code snippet below? I am encountering an issue when trying to invoke the useLocation method from react-router-dom. Upon researching online, I came across simil ...

Adjust the hue of the SVG sprite

I am currently using an SVG sprite as the background image for my project: .naar-logo { background: url(images/salt_sprite.svg) no-repeat -8px -78px; width: 36px; height: 49px; position: relative; top: 38px; } <div class="naar-logo ...

What is the best method for placing text over an image in Dreamweaver?

What steps should I take to overlay text on an image using Dreamweaver? Similar to the example linked below: https://i.stack.imgur.com/8GvkW.png Below is a snippet of my code: HTML <body> <main> <header> <img src="images/headerimag ...

What is the correct method for formatting text spacing?

A few months ago, I dabbled in web design and created a basic website. Now, I'm revisiting it to clean up the layout and make it more visually appealing. I initially used non-breaking spaces to separate paragraphs, but I know that's not optimal. ...

Combine SVGR with Material UI for a powerful design experience

Currently, I am experimenting with SVGR to convert my SVG into React components. My goal is to utilize <SvgIcon /> from Material UI and pass the converted component as a prop to it. Everything seems fine so far. However, SVGR stores these components ...

Closing a batch file after the React app is shut down can be achieved by utilizing a

Running my react application involves the use of a .bat file with the following commands: cd.. cd projects cd material cd server npm run dev Upon executing this script, it initiates cmd and launches my app in Chrome. Despite spending hours searching for ...

In what ways does React outperform Angular 1.x?

After reading up on this, it seems like React aggregates all DOM changes before making them. Couldn't Angular employ a similar mechanism? It already knows which DOM nodes need to be altered after the digest cycle -- why not coordinate the updates alto ...

How to style multiple tags using CSS

Is there a way to style specific tags in CSS? <style type="text/css"> [attribute*="test"] { background-color: red; } </style> However, this method does not seem to work for the following tags: <test-1> </test-1> <t ...

Is it necessary for each React component to have its own individual stylesheet?

Looking for some advice on React as a newbie here. I'm wondering whether each React component should have its own stylesheet. For instance, if I have my main App component that gets rendered to the browser, is it sufficient to include a CSS file the ...

Struggling to incorporate a nested If Else statement within a REACTJS component results in the error message "0 is not a function" popping

I am currently working on implementing an if-else statement in React. As a beginner in this language, I keep encountering the error "0 is not a function" whenever I load the app. In simple terms, I want to create a statement where if it's loading or d ...

"Utilizing multiple class names in Next.js to enhance website styling

Looking for a way to apply multiple classNames in Next.js, especially when dealing with variable classnames? I'm following the component level CSS approach. Take a look at my code and what I aim to achieve: import styles from "./ColorGroup.mod ...

The webpack-bundle-analyzer tool reveals that running webpack -p does not eliminate the development dependency react-dom.development.js

Here is my custom webpack configuration: const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const SO ...

Easily include the header component in all other components using React Router 4.1.1 without the need to import it

I have been searching for documentation on nested routes in version 4.1.1 of React Router on the website https://reacttraining.com/react-router. Unfortunately, I have not been able to find a solution. In older versions of React Router, nesting Routes was d ...

The login form is experiencing issues with submission when utilizing the submitFormHandler in ReactJS

In my single-page application, I'm working on creating a separate login page that will redirect the authenticated user to the main application. However, I'm encountering an issue where my submitFormHandler is not being invoked. The purpose of aut ...

Struggling to Retrieve Specific Keys for Individual Values in Firebase with React Native

I am currently experiencing difficulty obtaining a unique key for each value in the 'users1' table. firebase.database().ref('users1').once('value').then(snapshot => { var items = []; snapshot.forEach((child) => { ...

How can I resolve the issue of <td> being repeatedly displayed five times instead of just twice in PHP?

Can someone assist me with fixing this for loop issue? I am trying to display controls next to each item in the row, but it is showing 5 sets of controls instead of just 2. <tbody> <?php //retrieve list of supplies $numOfRows = 0; $result = my ...

Is it possible to utilize pm2 for maintaining the continuous operation of a Next.js application?

My AWS EC2 instance is dedicated to running my Next.js client side (with no backend at the moment). Currently, I need to manually enter "npm run develop" in the terminal for the site to run smoothly. However, I am looking for a way to keep this process run ...

Tips for turning Material UI Temporary Drawer button into an icon instead of text

I am currently implementing a navigation bar using Material UI and Temporary Drawer. When the user interacts with the hamburger menu icon, my goal is to have the menu smoothly fade-in on the screen and slide in from the right side. Most of the functionali ...

Some devices are experiencing issues with their camera not turning on during Next.js and Socket.IO video chats

Upon integrating video chat into my existing Next.js application, I encountered two specific issues. My tech stack includes Next.js version 10, socket.io version 4, socket.io-client version 4, and express. Being a novice in this area, I researched variou ...

Vue - Display components next to sidebar

Having an issue with the vue-sidebar-menu. The sidebar is appearing over the components instead of beside them. Here is a screenshot of the problem: <template> <div id="app"> <sidebar-menu :menu="menu" /> <vue-page-transit ...