Material-ui: [OutlinedInput] Label width is being calculated before fonts are loaded

Created on 3 Jul 2019  路  5Comments  路  Source: mui-org/material-ui

  • [x] This is not a v0.x issue.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 馃

What should happen is the following
Screenshot_1

Current Behavior 馃槸

But instead I get this
Screenshot_2

Notice that the TextField's outline is slightly overlaping the label.

This only happens when the page loads for the first time (Or after a hard refresh), and whenever a react re-render occurs, the problem is gone.

I also noticed that this problem happened when I changed the default font, and I think it has something to do with FOUT (Flash of unstyled text).

Is it possible that Mui calculates the label's gap width on the outline based on the font that loads first, before the new font style gets applied

PS: When I write something with Roboto font, then I change the font family to something else (in this case Tajawal) and give them the same font size, I notice that the same sentence I typed with Tajawal is a bit wider than the one with Roboto.

Can anyone help me solve this issue, and is there a way to load font styles before React manifests into the root element?

Your Environment 馃寧

| Tech | Version |
|--------------|---------|
| Material-UI | v4.1.3 |
| React | v16.8.6 |
| Browser | All |

bug 馃悰 TextField

Most helpful comment

We have a similar issue with the Tabs component: https://github.com/mui-org/material-ui/issues/7187. I'm not aware of any better solution than the ones we have explored in the tab linked issue. To sum-up:

  1. The action path: we could expose an action prop to ask for the component to update its position, synchronize the outline gap with it. It's an approach already deployed with a few other components.
  2. The font wait loading path: mount the React text field once the font is loaded (fontfaceobserver or webfontloader).
  3. In the future, we should consider using the ResizeObserver API for out of the box support:

All 5 comments

We have a similar issue with the Tabs component: https://github.com/mui-org/material-ui/issues/7187. I'm not aware of any better solution than the ones we have explored in the tab linked issue. To sum-up:

  1. The action path: we could expose an action prop to ask for the component to update its position, synchronize the outline gap with it. It's an approach already deployed with a few other components.
  2. The font wait loading path: mount the React text field once the font is loaded (fontfaceobserver or webfontloader).
  3. In the future, we should consider using the ResizeObserver API for out of the box support:

I dug into FontFaceObserver, and I found a solution

I loaded the font first and returned a promise that resolves when the font is loaded then renders the page

If you want a very simple solution to handle this and don't mind using experimental technology that is currently supported by most browsers here is an example...

constructor(props) {
    super(props);
    this.state={
        fontsLoaded: false,
    }
}

componentDidMount() {
    if (document.fonts) {
        document.fonts.ready
        .then(() => {
            this.setFontsLoaded(true)
        })
    }
}

setFontsLoaded(complete) {
    this.setState({fontsLoaded: complete})
}

render() {
    return(
        ...
        {this.state.fontsLoaded && renderView()}
        ...
    )
}

Thank you @stevenberdak, I ll try it as soon as possible, if you are interested on knowing how I got it to work, here is how:

  • First you install FontFaceObserver and import it into your file..
  • Then create an observer appFont = new FontFaceObserver('NAME_OF_FONT')
  • Then you return a promise that renders your app when it resolves (In this case when font is loaded)
    ```js
    import FontFaceObserver from 'fontfaceobserver';

const appFont = new FontFaceObserver('NAME_OF_FONT');

appFont.load().then(() => {
ReactDOM.render(rootElement, document.getElementById('root'))
})
```

Note that rootElement is a variable wrapping my <App /> and any other components.

We have explored a solution in #17680 that only relies on CSS to position the label. This should solve the problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

newoga picture newoga  路  3Comments

pola88 picture pola88  路  3Comments

ghost picture ghost  路  3Comments

FranBran picture FranBran  路  3Comments

ryanflorence picture ryanflorence  路  3Comments