DEV Community

Sibylle Sehl
Sibylle Sehl

Posted on

How to import a web font into your React App with styled components 4

Tired of being limited to requesting fonts over a CDN? Look no further.

You might be required to import a font for a number of reasons - ranging from buying corporate licenses for certain fonts, to availability concerns or even because your favourite font isn't available through a CDN (Content Delivery Network).

Since I've started working as a developer, I've learned how to import a web font directly rather than linking to a CDN where the font might be hosted. Since I didn't really know where to start, I thought I'd write up this quick tutorial to show you how you can accomplish this in a React setting using styled components version 4 - my favourite way of writing CSS in React apps.

Let's get down to business

First of all, you need select the font you want to import and download it in woff and woff2 format. Woff (and later Woff2) stands for Web Open Font Format and is the recommended font format by the World Wide Web Consortium (W3C). Its format specific compression ensures its performance in all browsers and furthermore reduces web font latency as opposed to requesting fonts from a CDN.

There are a few sites where you can download these, for example:

Pick anything you like!
I'd advise you to import at least those two font formats, woff and woff2, since they have been recommended by the W3C and are widely supported on all browsers.

In your React project, create a folder in your src folder and name it 'fonts'. In this folder create a file which you call fonts.js - this will contain the imports for your fonts and will later make them available to the rest of your app.

In the same folder, now place the two font files you have just downloaded. This will make them accessible for your app to import them correctly. After doing this, your file structure should look similar to this:

src
|__fonts
    |__fonts.js
    |__nameOfYourFont.woff2
    |__nameOfYourFont.woff

Now, let's actually write some code into the fonts.js file so 'styled components' can import them as a Global Font.

In your fonts.js file import the { createGlobalStyle } from 'styled-components'. This is a handy little helper that handles global css styles in your app. If you want to to dive in, visit createGlobalStyle on the styled components documentation. After doing that, you have to import the fonts into your file and declare them in a font-face declaration.

import { createGlobalStyle } from 'styled-components';

import NameOfYourFontWoff from './nameOfYourFont.woff';
import NameOfYourFontWoff2 from './nameOfYourFont.woff2';

export default createGlobalStyle`
    @font-face {
        font-family: 'Font Name';
        src: local('Font Name'), local('FontName'),
        url(${NameOfYourFontWoff2}) format('woff2'),
        url(${NameOfYourFontWoff}) format('woff');
        font-weight: 300;
        font-style: normal;
    }
`;

This will import your chosen font in both woff and woff2 formats and make it accessible through the fonts file.

But that's only half of the battle done.

While we have imported the specific fonts, we haven't actually imported these in our App yet.

At the top of the App.js file, after importing React, write

import GlobalFonts from './fonts/fonts';

// assuming you places fonts in your src folder as described above.

Somewhere in the App.js file, preferably just below a normal styled component that would typically contain site layout or similar and doesn't need any font styles, place the GlobalFonts component in your return of the render:

render() {
    return (
        <Wrapper> 
            <GlobalFonts />
    // ...
        </Wrapper>
    );
}

After doing this, you are free to use your font anywhere in your styles as you choose. In any styled-components file, just declare (for example):

const AwesomeHeadline = styled.h1`
    font-family: 'Font Name';
`;

export default AwesomeHeadline;

Et voila, you just imported your web font and used it in a Headline!

I hope this helps you to import fonts in the future, be it for work or that awesome personal project with that personal touch!

Top comments (19)

Collapse
 
anteronunes profile image
Antero Nunes • Edited

Thank yooouuuuu!!!! ♥♥♥

And for those using TypeScript, create a fonts.d.ts file in /src folder and include the font extensions you want to import, like below ↓↓↓:

declare module '*.woff';
declare module '*.ttf';

  • Update - September 2021 | TTF and OTF Fonts:

Don't write formats like format('ttf') or format('otf'), because it is not gonna work.
If you are using TTF or OTF fonts, in the format options of @font-face, you should write as:
format('truetype');
format('opentype');

Don't use spaces when naming your font files
Wrong: My Awesome Font.ttf
Right: MyAwesomeFont.ttf

That's it! Now your project's Typescript understands fonts.

Collapse
 
negativefriction profile image
Chris Pete

I created an account on this website just to like this and say thank you. Been tearing out my hair trying to figure out why this darned font wouldn't load-- it was because of the spaces. Thank you for this.

Collapse
 
john1625b profile image
john1625b • Edited

great article. If I want all my components to use this font without specifying the font again and again for every component, how would I do that?

edit: in the global styles file do

* {
font-family:...
}

Collapse
 
khusseini profile image
Khairi Husseini

Do you by change know how to handle the font delivery when using this approach in a component library?
I setup my library to be bundled with rollupjs and the @rollup/plugin-url, however when running the implementing react application, the fonts are requested directly via http ./[hasedname].woff which results in a 404.

Collapse
 
codeguruedison profile image
Ayaskanta Samal

Did you find any solutions for this?

Collapse
 
earthnoob profile image
Jo

Great post! What if I were to import a whole family of fonts?

Collapse
 
verthon profile image
Krzysztof Sordyl • Edited

Thank you very much. Very informative. For people like me who are using Typescript you might want to declare your your font file types described here:
designcise.com/web/tutorial/how-to...

Collapse
 
michelestaffiere profile image
Michele

Followed step by step (except for downloading two font formats) and downloaded my fonts from the site provided but just get an error

 Uncaught SyntaxError: The requested module '/src/fonts/JetbrainsMono.woff?import' does not provide an export named 'JetBrainsMono' (at fonts.js:2:9)
Enter fullscreen mode Exit fullscreen mode
import { createGlobalStyle } from 'styled-components';
import {JetBrainsMono} from './JetbrainsMono.woff';

export default createGlobalStyle`
    @font-face {
        font-family: JetBrains Mono;
        src: local('JetBrains Mono'), local('JetBrainsMono'),
        url(${JetBrainsMono}) format('woff');
        font-weight: 700;
        font-style: normal;
    }
`;
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kanapka94 profile image
Adam

You can also to this:

// simplified example

const App = () => <StyledContainer>
  <StyledButton>
    Click
  </StyledButton>
</StyledContainer>

const StyledContainer = styled.div`
    @import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');
`;

const StyledButton = styled.button`
    font-family: 'Lato', sans-serif;
`;

Enter fullscreen mode Exit fullscreen mode
Collapse
 
gugadev profile image
gugadev

Interesing approach! Thanks for share it.

Collapse
 
danphp7 profile image
Carlos Daniel

It works on React Native ?

Collapse
 
raghavsharma profile image
Raghav Sharma

Thank you ❤️, you saved my life!