Move @font-face declaration from global CSS into MUI Theme

98 Views Asked by At

I have the below index.css file:

//Index.css
...
@font-face {
  font-family: "My Font";
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/public/fonts/my-font.eot);
  src: url(/public/fonts/my-font.eot#iefix) format("embedded-opentype"),
    url(/public/fonts/my-font.otf) format("otf"),
    url(/public/fonts/my-font.svg) format("svg"),
    url(/public/fonts/my-font.woff) format("woff"),
    url(/public/fonts/my-font.woff2) format("woff2");
}
...

Then I have both GlobalStyles.jsx & CustomThemeProvider.jsx files for creating my MUI theme, as below:

// GlobalStyles.jsx
import GlobalStyles from "@mui/material/GlobalStyles";

const importGlobalStyles = (
  <GlobalStyles
    styles={{
      body: {
        backgroundImage: `url(${window.theme.backgroundLink})`,
        backgroundColor: `${window.theme.colors.pageBackground}`,
        color: `${window.theme.colors.font}`,
        fontFamily: `-apple-system, ${window.theme.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
        "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;`,
      },
    }}
  />
);

export default importGlobalStyles;

And

//CustomeThemeProvider.jsx

import React from "react";
import { createTheme, ThemeProvider } from "@mui/material/styles";

export const appTheme = createTheme({
  palette: {
    primary: {
      main: window.theme.colors.primary,
    },
    error: {
      main: window.theme.colors.error,
    },
  },
typography: {
    allVariants: {
      fontFamily: `-apple-system, ${window.theme.fonts.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`,
    },
    fontFamily: `-apple-system, ${window.theme.fonts.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`,
    h1: {
      fontWeight: 500,
      fontSize: "30pt",
      lineHeight: "40pt",
      color: window.theme.colors.primary,
    },
},
});

const CustomThemeProvider = (props) => {
  const { children } = props;

  return <ThemeProvider theme={appTheme}>{children}</ThemeProvider>;
};

export default CustomThemeProvider;

This all works fine, allowing me to customize the theme by setting window.xxx theme variables in a public config.js file, which I can then pass into the theme (you can see them below passed in using window.theme.xxx).

The problem I have, is I can't figure out how to lift the @font-face from index.css and move it into the theme setup that I have, so I can set the theme links as variables to pass in. That way, I can white-label fonts when rebuilding this app, etc.

Any thoughts as to how best achieve this? I've read through MUI docs and haven't found anything super helpful. We don't use CSSBaseline, and don't particularly want to implement either as it's unnecessary in our current implementation. Any suggestions as to how to do this please?

2

There are 2 best solutions below

0
Milind On BEST ANSWER

You can Define font URLs as theme variables and then use the defined theme variables in the @font-face declaration and then Import and apply the @font-face styles within your MUI theme.

For example -

CustomThemeProvider.jsx:

import React from "react";
import { createTheme, ThemeProvider } from "@mui/material/styles";

export const appTheme = createTheme({
  palette: {
    primary: {
      main: window.theme.colors.primary,
    },
    error: {
      main: window.theme.colors.error,
    },
  },
  typography: {
    allVariants: {
      fontFamily: `-apple-system, ${window.theme.fonts.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`,
    },
    fontFamily: `-apple-system, ${window.theme.fonts.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`,
    h1: {
      fontWeight: 500,
      fontSize: "30pt",
      lineHeight: "40pt",
      color: window.theme.colors.primary,
    },
  },
  // Add font URLs as theme variables
  fonts: {
    myFont: {
      eot: "/public/fonts/my-font.eot",
      otf: "/public/fonts/my-font.otf",
      svg: "/public/fonts/my-font.svg",
      woff: "/public/fonts/my-font.woff",
      woff2: "/public/fonts/my-font.woff2",
    },
  },
});

const CustomThemeProvider = (props) => {
  const { children } = props;

  return <ThemeProvider theme={appTheme}>{children}</ThemeProvider>;
};

export default CustomThemeProvider;

GlobalStyles.jsx

import React from "react";
import { GlobalStyles as MuiGlobalStyles } from "@mui/material";
import { appTheme } from "./CustomThemeProvider";

const GlobalStyles = (
  <MuiGlobalStyles
    styles={{
      body: {
        backgroundImage: `url(${window.theme.backgroundLink})`,
        backgroundColor: `${window.theme.colors.pageBackground}`,
        color: `${window.theme.colors.font}`,
        fontFamily: appTheme.typography.allVariants.fontFamily,
        // Other styles...
      },
      // Add @font-face styles using theme variables
      '@font-face': {
        fontFamily: 'My Font',
        fontStyle: 'normal',
        fontDisplay: 'swap',
        fontWeight: 400,
        src: `
          url(${appTheme.fonts.myFont.eot}),
          url(${appTheme.fonts.myFont.eot}#iefix) format("embedded-opentype"),
          url(${appTheme.fonts.myFont.otf}) format("otf"),
          url(${appTheme.fonts.myFont.svg}) format("svg"),
          url(${appTheme.fonts.myFont.woff}) format("woff"),
          url(${appTheme.fonts.myFont.woff2}) format("woff2")
        `,
      },
    }}
  />
);

export default GlobalStyles;
1
Romer On

Define the font URLs as variables in your CustomThemeProvider.jsx or in a separate configuration file (e.g., fontConfig.js).

// fontConfig.js

const fontUrls = {
  eot: "/public/fonts/my-font.eot",
  otf: "/public/fonts/my-font.otf",
  svg: "/public/fonts/my-font.svg",
  woff: "/public/fonts/my-font.woff",
  woff2: "/public/fonts/my-font.woff2",
};

export default fontUrls;
  1. Import the fontUrls object in your CustomThemeProvider.jsx.
// CustomThemeProvider.jsx
import React from "react";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import fontUrls from "./fontConfig"; // Import the fontUrls object

export const appTheme = createTheme({
  // ... Your existing theme configuration ...

  // Add the font URLs using the imported fontUrls object
  typography: {
    // ... Your existing typography configuration ...

    fontFamily: `-apple-system, ${window.theme.fonts.fontFamilyName}, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`,
  },
  overrides: {
    MuiCssBaseline: {
      // Include the font URLs as variables
      "@font-face": {
        fontFamily: "My Font",
        fontDisplay: "swap",
        fontWeight: 400,
        src: `
          url(${fontUrls.eot}) format("embedded-opentype"),
          url(${fontUrls.woff2}) format("woff2"),
          url(${fontUrls.woff}) format("woff"),
          url(${fontUrls.ttf}) format("truetype"),
          url(${fontUrls.svg}) format("svg");
        `,
      },
    },
  },
});

const CustomThemeProvider = (props) => {
  const { children } = props;

  return <ThemeProvider theme={appTheme}>{children}</ThemeProvider>;
};

export default CustomThemeProvider;

By following these steps, you've moved the @font-face declaration into your MUI theme setup, making it more manageable and customizable.