Using a custom font with Remix Run and Chakra UI
Tags: remix, chakraui, font, typescript
Published: 2022-02-12 02:49:25

Recently, I needed to install a custom font in a site using Remix Run front end framework. The documentation that Chakra has regarding fonts did not work for me. So if it doesn't work for you, here's how to do that.

This guide should also work if you are not using Chakra UI and only want to use css styling.

In this example I am using a self hosted font and using the Chakra theme to style the `<Text>` and `<Heading>` tags. But you can also add a class in the css file to fontstyle any text.

Go to [Google Web Fonts Helper](https://google-webfonts-helper.herokuapp.com/fonts) and choose the font you need. [Raleway](https://fonts.google.com/specimen/Raleway) is the font used as the example in this guide.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ycdw3xxki4d2ys3wq9wq.png)

Download the font files. If you choose modern browsers, you will get .woff and .woff2 files.

Place these files inside a new "raleway" folder: app/public/fonts/raleway

Create a .css file. For instance: index.css located in app/styles directory. Inside this css file, place the 
`@font-face` code from the fonts helper.

Optional: you can also specify a new css class so that you can style any text with this font.

```
@font-face {
    font-family: 'Raleway';
    font-style: normal;
    font-weight: 400;
    src: local(''),
         url('/fonts/raleway/raleway-v26-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
         url('/fonts/raleway/raleway-v26-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */

.raleway {
    font-family: "Raleway";
}
  }
```

Chakra UI uses themes. Make a new theme.tsx file, in your /app directory for example.

```
import { extendTheme, theme as defaultTheme } from "@chakra-ui/react";

const theme = extendTheme({
    ...defaultTheme,
    colors:{
        ...defaultTheme.colors,
    },
    fonts:{
        heading: "'Raleway', sans-serif;",
        body: "'Raleway', sans-serif;",
    },
})

export default theme
```

In the entry point of the application, root.tsx file (where the ChakraProvider tag is), add the theme to the tag.

```
export default function App() {
  return (
    <Document>
     <ChakraProvider theme={theme}>
       <CSSReset/>
       <Outlet />
     </ChakraProvider>
    </Document>
  );
}
```

Import the css file into the file for the webpage you want to style. Use the links() function.

```
import styles from "~/styles/index.css";
import {
  Links,LiveReload,Meta,Outlet,Scripts,ScrollRestoration,useCatch,
  useLoaderData
} from "remix";
import { Heading, Text } from '@chakra-ui/react'


export const links = () => {
  return [{ rel: "stylesheet", href: styles }];
};
```

If you use the Chakra UI `<Heading>` or `<Text>` tag (corresponding to the heading: and body: in the theme.tsx) the font should be the custom font family displaying on the webpage. 

```
// app/routes/index.tsx
export default function Index() {
  return (
    <>
      <div>
        <h1 className="raleway">ABCDEFG Test of Font using 
        className
        </h1>
        <Heading>ABCDEFG Test of Font from Heading</Heading>
        <Text>ABCDEFG Test of font from text</Text>
      </div>
    </>
```

If you created a css class, you can also see your custom font by using the className, e.g. `<p className='raleway'>Test</p>`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ep4vf6jujpiylj8mxnb.png)
 

For reference I have put the full app/root.tsx and app/routes/index.tsx below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5l1uya23atfkziiuvlxf.png)
 

root.tsx
```
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
  useCatch,
  useLoaderData
} from "remix";
import type { MetaFunction } from "remix";
import { Box, ChakraProvider, CSSReset, Heading } from '@chakra-ui/react'
import theme from "~/theme";


export const meta: MetaFunction = () => {
  return { title: "New Remix App" };
};

export default function App() {
  return (
    <Document>
     <ChakraProvider theme={theme}>
       <CSSReset/>
       <Outlet />
     </ChakraProvider>
    </Document>
  );
}


function Document({
  children,
  title = "App title"
}: {
  children: React.ReactNode;
  title?: string;
}) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <Meta />
        <title>{title}</title>
        <Links />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
        {process.env.NODE_ENV === "development" && <LiveReload />}
      </body>
    </html>
  );
}

export function ErrorBoundary({ error }: { error: Error }) {
  return (
    <div>
      <Document title='Error!'>
      <ChakraProvider >
        <Box>
          <Heading as='h1'>There was an error</Heading>
        </Box>
      </ChakraProvider>
    </Document>
    </div>
    
  )
}

export function CatchBoundary() {
  let caught = useCatch()

  return (
    <Document title={`${caught.status} ${caught.statusText}`}>
      <ChakraProvider>
        <Box>
          <Heading as='h1'>
            {caught.status} {caught.statusText}
          </Heading>
        </Box>
      </ChakraProvider>
    </Document>
  )
}
```

index.tsx
```
import styles from "~/styles/index.css";
import {Links,LiveReload,Meta,Outlet,Scripts,ScrollRestoration,useCatch,useLoaderData} from "remix";
import { Box, Center, ChakraProvider, Circle, CSSReset, Heading, Text, ThemeProvider } from '@chakra-ui/react'


export const links = () => {
  return [{ rel: "stylesheet", href: styles }];
};

export default function Index() {

  return (
    <>

      <div>
        <h1 className="raleway">ABCDEFG Test of Font using className</h1>
        <Heading>ABCDEFG Test of Font from Heading</Heading>
        <Text>ABCDEFG Test of Font from Text</Text>
      </div>

    </>

  );
}
```