10

I have a next.config.js file that has the following configuration:

const withSass = require('@zeit/next-sass');
const withCss = require('@zeit/next-css');

module.exports = withSass(withCss({
  webpack (config) {
    config.module.rules.push({
      test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
      use: {
        loader: 'url-loader',
        options: {
          limit: 100000,
          publicPath: './',
          outputPath: 'static/',
          name: '[name].[ext]'
        }
      }
    })

    return config
  }
}));

This is great because it runs my semantic ui css files.

Now I have a problem. I can't seem to successfully import any google font url. I tried downloading the ttf file into my file path and tried to reference it with the @import scss function. However I get a GET http://localhost:3000/fonts/Cabin/Cabin-Regular.ttf net::ERR_ABORTED 404 (Not Found) error

Here is what I'm trying to do with google font:

@font-face {
  font-family: 'Cabin';
  src: url('/fonts/Cabin/Cabin-Regular.ttf')  format('truetype');
}

$font-size: 100px;
.example {
  font-size: $font-size;
  font-family: 'Cabin', sans-serif;
}

I have also downloaded the relevant npm dependencies:

"@zeit/next-css": "^1.0.1",
"@zeit/next-sass": "^1.0.1",
"file-loader": "^2.0.0",
"next": "^7.0.2",
"node-sass": "^4.9.4",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.83.0",
"url-loader": "^1.1.2"

7 Answers 7

11

I know in Next.js 9.3, you can copy the @import statement from Google Fonts:

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

and place this in some css file, lets say styles/fonts.css like so:

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

.jost {
  font-family: 'Jost', sans-serif;
}

Then import that inside of your global _app.js file like so:

import `../styles/fonts.css`

Now you have global access to that class containing the Google Font in every next.js page

Sign up to request clarification or add additional context in comments.

1 Comment

I would consider this as the best practice.
8

I think the other solution is to use fonts directly from Google. Just customize _app.js file and add a <link rel="stylesheet" /> in the <Head />

Example _app.js

import React from 'react';
import App, { Container } from 'next/app';
import Head from 'next/head';

export default class MyApp extends App {
  static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    return { pageProps };
  }

  render() {
    const { Component, pageProps } = this.props;

    return (
      <Container>
        <Head>
          <link
            href="https://fonts.googleapis.com/css?family=Cabin"
            rel="stylesheet"
            key="google-font-cabin"
          />
        </Head>

        <Component {...pageProps} />

        <style global jsx>{`
          body {
            font-family: 'Cabin', sans-serif;
          }
        `}</style>
      </Container>
    );
  }
}

4 Comments

what would you consider as best practice? housing the font in local folders or what you just suggested?
I would go with the approach when I use fonts from Google via API instead of downloading them locally. Some benefits I see: 1. If I need to add more fonts from google I dont need to download anything just add a font name to the URL and that's it 2. No need to tweak next.js webpack config to load fonts
That works great. I would put it to _document.js though.
I would consider a local copy best practice - along with the css font display setting you can avoid an unecessary network request
2
 class NextApp extends App {
  render() {
    const { Component } = this.props
    return (
          <React.Fragment>
            <Component {...pageProps} />

            <style jsx="true" global>{`

              @import url('https://fonts.googleapis.com/css?family=Roboto');

              body {
                margin: 0;
                font-family: 'Roboto', sans-serif;
              }

            `}</style>

          </React.Fragment>
        </Provider>
      </Container>
    )
  }
}

Including the font url from Google Fonts in styled-jsx worked for me.

Comments

1

As per the latest docs you can now add global css by updating the _app.js file and importing your css style. Follow the steps below

  1. Create custom _app.js file in the pages directory by following the docs.
  2. Add your styles.css file to the pages directory.
  3. Include the styles as below

// _app.js

// Import styles
import './styles.css'

// Function to create custom app
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

// Export app
export default MyApp

and done. These styles styles.css will apply to all pages and components in your application. Due to the global nature of stylesheets, and to avoid conflicts, you may only import them inside _app.js.

Comments

0

I had to put the files into the static folder for it to work, must've been a specific setup for rendering images and fonts in nextjs

Comments

0

If you are using a functional custom app, then you can add google fonts or any cdn linked fonts to the head of the whole app as follows:

import Head from 'next/head';

// Custom app as a functional component
function MyApp({ Component, pageProps }) {
  return (
    <>
      <Head>
        <link
          href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400;600;700&display=swap" rel="stylesheet"/>
      </Head>
      <Component {...pageProps}/>
    </>
  )
}

MyApp.getInitialProps = async ({ Component, ctx }) => {
  let pageProps = {};
  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx);
  }

  return { pageProps };
};

// Export app
export default MyApp

now you can use css to apply the font family to the body element to get the font applied throughout the webiste, as shown below.

body {
  font-family: 'Source Sans Pro', sans-serif;
}

Comments

-1

Hhis is now how I am currently loading external fonts nonblocking. In _document.js head:

<script dangerouslySetInnerHTML={{__html: '</script><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" media="print" onload="this.media=\'all\'" /><script>' }} />
  • dangerouslySetInnerHTML and some script hacking to work around onload otherwise being removed from _document.js until this is resolved

source

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.