reactjstypescriptmaterial-uistyled-componentsjss

How to add a custom font to the themeprovider in styled components?


I'm building a React app using material-ui styled-components with TypeScript.

I'm trying to use a custom font with my styled components, but I'm struggling to get it to work.

First thing I did was I created a globalStyles.ts file createGlobalStyle:

import { createGlobalStyle } from "styled-components";

export const theme = {
  primaryBlue: "#0794B4",
  secondaryBlue: "#043157",
  primaryWhite: "#fff"
};

const GlobalStyle = createGlobalStyle`
  @font-face {
    font-family: pala;
    src: url("./assets/pala.ttf") format('truetype');
    font-weight: normal;
    font-style: normal;
  }
  html {
    font-size: 10px;
  }
`;
export default GlobalStyle;

I added the ThemeProvider and the GlobalStyle to my app:

import React, { Component } from "react";
import "./App.css";
import NavBar from "./components/NavBar";
import { ThemeProvider } from "styled-components";
import GlobalStyle, { theme } from "./globalStyles";

class App extends Component {
  render() {
    return (
      <ThemeProvider theme={theme}>
        <div className="App-header">
          <NavBar title="MyCompany" />
          <GlobalStyle />
        </div>
      </ThemeProvider>
    );
  }
}

export default App;

And then I tried to use this font from within my styled component:

import React, { PureComponent } from "react";
import styled from "styled-components";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";

export const StyledAppBar = styled(AppBar)``;
export const StyledToolbar = styled(Toolbar)``;
export const StyledTypography = styled(Typography)`
  && {
    font-family: pala;
    font-size: 10rem;
    color: ${props => props.theme.primaryWhite};
  }
`;

export interface Props {
  title: string;
}

export class NavBar extends PureComponent<Props> {
  render() {
    return (
      <StyledAppBar>
        <StyledToolbar>
          <StyledTypography>{this.props.title}</StyledTypography>
        </StyledToolbar>
      </StyledAppBar>
    );
  }
}

export default NavBar;

The styles for the color and the font size are correctly applied, but the custom font is not. Do I somehow have to add the custom font to the ThemeProvider and use it via props.theme.font? Or am I doing something wrong?


Solution

  • To declare a custom font with styled-components createGlobalStyle:

    1. import your font as you would import a module
    2. interpolate it in your @font-face declaration using tagged template literals.

    Here's your globalStyles.ts:

    // globalStyles.ts
    
    import { createGlobalStyle } from "styled-components";
    // 1. import the font
    import pala from "./assets/pala.ttf";
    
    export const theme = {
      primaryBlue: "#0794B4",
      secondaryBlue: "#043157",
      primaryWhite: "#fff"
    };
    
    // 2. interpolate it using tagged template literals
    const GlobalStyle = createGlobalStyle`
      @font-face {
        font-family: pala;
        src: url(${pala}) format('truetype');
        font-weight: normal;
        font-style: normal;
      }
      html {
        font-size: 10px;
      }
    `;
    
    export default GlobalStyle;
    

    If you want to learn more about tagged template literals in styled-components, Max Stoiber (who created styled-components) wrote a really nice article about it.