Material-ui: Custom font isn't loading on custom theme for Material UI

Created on 17 Dec 2019  路  24Comments  路  Source: mui-org/material-ui

Current Behavior 馃槸

I'm using a custom font in my React web application. So I wrote this code:

import React, { FunctionComponent } from 'react'
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles'
import SofiaProLightTtf from '../../assets/font/sofia-pro-light.ttf'
import SofiaProTtf from '../../assets/font/sofia-pro-regular.ttf'

const sofiaPro = {
  fontFamily: 'Sofia Pro',
  fontStyle: 'normal',
  fontWeight: 100,
  src: `url(${SofiaProTtf})`
}

const sofiaProLight = {
  fontFamily: 'Sofia Pro Light',
  fontStyle: 'normal',
  fontWeight: 100,
  src: `url(${SofiaProLightTtf})`
}

const theme = createMuiTheme({
  typography: {
    fontFamily: 'Sofia Pro',
    body1: {
      fontFamily: 'Sofia Pro Light'
    }
  },
  overrides: {
    MuiCssBaseline: {
      '@global': {
        '@font-face': [sofiaPro, sofiaProLight]
      }
    }
  }
})

const Theme: FunctionComponent = ({ children }) => (
  <MuiThemeProvider theme={theme}>{ children }</MuiThemeProvider>
)

export default Theme

But it isn't working. So I tried to customize the font using plain CSS.

I found a workaround removing the overrides property in createMuiTheme and with this CSS:

<style>
  @font-face {
    font-family: 'Sofia Pro';
    font-style: normal;
    font-weight: 100;
    src: url("/65e0f064b96a52b92f7293b673054b0b.ttf");
  }

  @font-face {
    font-family: 'Sofia Pro Light';
    font-style: normal;
    font-weight: 100;
    src: url("/d15399628129cc8121c08073df25f0dd.ttf");
  }
</style>

But it is a very bad workaround...
I opened a question on Stack Overflow but nobody answered, so I think that it's a bug.

I'm using the latest Material UI version:

"@material-ui/core": "4.7.0",
"@material-ui/lab": "4.0.0-alpha.34",

Expected Behavior 馃

We need be able to load a custom font using only createMuiTheme, without any custom CSS.

Steps to Reproduce 馃暪

  1. Create a new project. You'll need to add this rule on your webpack.config.js:
  {
    test: /\.ttf$/,
    use: 'file-loader',
    exclude: /node_modules/,
  },
  1. Add some custom fonts on your project, and copy and paste the first code block on this issue

  2. On your index.tsx, use:

import React from 'react'
import ReactDOM from 'react-dom'
import Theme from './theme'

const App = () => (
  <Theme>
    <p>hello world</p>
  </Theme>
)

ReactDOM.render(<App />, document.getElementById('app'))
  1. The custom font wasn't load.

Context 馃敠

I need to use a custom font. Beside I found a workaround, I would like to have a better code.

Your Environment 馃寧

| Tech | Version |
| ----------- | ------- |
| Material-UI | v4.7.0 |
| React | 16.12.0 |
| Browser | Chore, Firefox and Safari |
| TypeScript | 3.7.2 |

support

Most helpful comment

@oliviertassinari I can confirm that changing the documentation there would likely have prevented me from seeing this issue. Thanks, and apologies for assuming this issue was a bug rather than an onboarding issue.

CssBaseline is a component that I'd internally considered "separate" due to the fact that it's effectively a CSS reset under normal circumstances, so placing inside ThemeProvider directly didn't even occur to me; I had been looking in the wrong place, assuming it was either a bug or I'd been overriding incorrectly.

All 24 comments

馃憢 Thanks for using Material-UI!

We use GitHub issues exclusively as a bug and feature requests tracker, however,
this issue appears to be a support request.

For support, please check out https://material-ui.com/getting-started/support/. Thanks!

If you have a question on StackOverflow, you are welcome to link to it here, it might help others.
If your issue is subsequently confirmed as a bug, and the report follows the issue template, it can be reopened.

@oliviertassinari Thank you for you notice quickly my issue, but I think that it's a bug, not a support.
I already opened a question on Stack Overflow and nobody answered that.

I'm sorry if I'm doing something wrongly.

Using regular CSS sounds like a good solution too.

@oliviertassinari Well... I think that it isn't a good solution.
I wrote a slightly better code using tsx:

const Theme: FunctionComponent = ({ children }) => (
  <>
    <style
      dangerouslySetInnerHTML={{__html: `
        @font-face {
          font-family: 'Sofia Pro';
          font-style: normal;
          font-weight: 100;
          src: url('/${SofiaProTtf}');
        }

        @font-face {
          font-family: 'Sofia Pro Light';
          font-style: normal;
          font-weight: 100;
          src: url('/${SofiaProLightTtf}');
        }`}
      }
    />
    <MuiThemeProvider theme={theme}>{ children }</MuiThemeProvider>
  </>
)

But it's still very awful because:

  • no type safe
  • no highlighting or code completion
  • since it isn't called by createMuiTheme neither any code on Material UI, new updates on this library could break this hack

Why is this closed while there is no real fix for a new bug?

@stephankaag Because @oliviertassinari prefer a workaround over fix this bug.

I believe it's a support request.

Just like https://github.com/mui-org/material-ui/issues/18826 is a support request?

@oliviertassinari Sorry, but I don't agree. It isn't a support request, but a bug.
It's a weird behaviour and, as like I already said here, it requires a workaround that has many disadvantages.

Look, I'm needing to use something called **DANGEROUS**SetInnerHTML and to define the style of Material UI components outside of createMuiTheme.

@stephankaag Yes, modules duplication.
@macabeus What's wrong with https://material-ui.com/customization/typography/#self-hosted-fonts? Did you render the CssBasline component?

@oliviertassinari overrides.MuiCssBaseline['@global']['@font-face'] isn't working.
For some reason, the component requires the font (Sofia Pro in this case), but it wasn't requested by browser.

image

image

Using CssBaseline component, I have a different problem.
I want this (my code with workaround works fine):
image

But with CssBaseline (and with the first code that I wrote in this issue) I'll have this:
image

It isn't Sofia Pro font, also it changes the style of others components.

@stephankaag Do you have these same problems?

Yep

Do you have a reproduction?

I'm having this same issue. CssBaseline is also always setting the font-family to "Roboto", "Helvetica", "Arial", sans-serif.

It appears that CssBaseline doesn't actually set @font-face in its styles JSS, and it sets things like font-family from computed values from typography.

This is definitely a bug, because doing the exact steps specified in the documentation doesn't actually work.

I also question why it's preferable to override CssBaseline in the first place. typography exists in the theme API, and this is 100% a typography-related feature. In my opinion, typography should have a key called fontFaces on it consisting of JssFontface[], and JssFontFace's type definitions should be exported, so that I can validate my custom font faces against it.

import { JssFontFace } from '@material-ui/core'; 

const sofiaPro: JssFontface = { 
  fontFamily: 'Sofia Pro',
  fontWeight: 400,
  ... 
};
const sofiaProLight: JssFontFace = {
  fontFamily: 'Sofia Pro',
  fontWeight: 300,
  ...
};

const theme = createMuiTheme({
  typography: {
    fontFamily: [sofiaPro.fontFamily].join(','),
    fontFaces: [sofiaPro, sofiaProLight]
  }
})

Do you have a reproduction we can look at?

@oliviertassinari give me just a minute to put one together, the current project I'm in is still fairly small, but a GHE repo.

@oliviertassinari here you go: https://github.com/kevin-lindsay-1/mui-test

@kevin-lindsay-1 What do you think of this patch of the documentation?

````diff
diff --git a/docs/src/pages/customization/typography/typography.md b/docs/src/pages/customization/typography/typography.md
index 22607df60..50196e4b3 100644
--- a/docs/src/pages/customization/typography/typography.md
+++ b/docs/src/pages/customization/typography/typography.md
@@ -68,6 +68,13 @@ const theme = createMuiTheme({
},
},
});
+
+// ...
+
+

  • {children}
    +
    ```

## Font size

````

Do you want to work on a pull request? :)

I think that it isn't work very well to fix this bug, as well I said here.

I'm writing a reproduction...

@oliviertassinari Done: https://www.dropbox.com/s/7w7kpeuqpwjw5eb/web.zip?dl=0
Use yarn and yarn start to run it.

@macabeus I'm sorry, I won't have time to look at it. Now, I'm pretty sure it's working, that it's a teaching issue. You can combine the reproduction of @kevin-lindsay-1 with my proposed improvements of the docs to have a working version.

Once you figure the issue out, we would love to hear about the step that you have missed, so we can look into better docs.

@oliviertassinari I can confirm that changing the documentation there would likely have prevented me from seeing this issue. Thanks, and apologies for assuming this issue was a bug rather than an onboarding issue.

CssBaseline is a component that I'd internally considered "separate" due to the fact that it's effectively a CSS reset under normal circumstances, so placing inside ThemeProvider directly didn't even occur to me; I had been looking in the wrong place, assuming it was either a bug or I'd been overriding incorrectly.

Wow, thanks @kevin-lindsay-1 !

Thanks @kevin-lindsay-1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

reflog picture reflog  路  3Comments

iamzhouyi picture iamzhouyi  路  3Comments

mattmiddlesworth picture mattmiddlesworth  路  3Comments

ryanflorence picture ryanflorence  路  3Comments

finaiized picture finaiized  路  3Comments