Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OutlinedInput] Label width is being calculated before fonts are loaded #16465

Closed
2 tasks done
rofazayn opened this issue Jul 3, 2019 · 9 comments · Fixed by #17680
Closed
2 tasks done

[OutlinedInput] Label width is being calculated before fonts are loaded #16465

rofazayn opened this issue Jul 3, 2019 · 9 comments · Fixed by #17680
Labels
bug 🐛 Something doesn't work component: text field This is the name of the generic UI component, not the React module!

Comments

@rofazayn
Copy link

rofazayn commented Jul 3, 2019

  • This is not a v0.x issue.
  • 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
@rofazayn rofazayn closed this as completed Jul 3, 2019
@rofazayn rofazayn reopened this Jul 3, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 3, 2019

We have a similar issue with the Tabs component: #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:

@rofazayn
Copy link
Author

rofazayn commented Jul 3, 2019

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

@rofazayn rofazayn closed this as completed Jul 3, 2019
@rofazayn rofazayn reopened this Jul 3, 2019
@oliviertassinari oliviertassinari added the component: text field This is the name of the generic UI component, not the React module! label Jul 21, 2019
@oliviertassinari oliviertassinari changed the title Text field's outline overlaps label [OutlinedInput] Label width is being calculated before fonts are loaded Jul 21, 2019
@stevenberdak
Copy link

stevenberdak commented Sep 3, 2019

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()}
        ...
    )
}

@rofazayn
Copy link
Author

rofazayn commented Sep 4, 2019

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)
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.

@oliviertassinari
Copy link
Member

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

@sebascomeau
Copy link

sebascomeau commented Jan 16, 2021

My solution with version 5.

    /* start: change outline fiels label text size */
    MuiInputLabel: {
      styleOverrides: {
        outlined: {
          '&$shrink': {
            transform: 'translate(14px, -6px) scale(0.9)',
          },
        },
      },
    },
    MuiOutlinedInput: {
      styleOverrides: {
        notchedOutline: {
          '& > legend': {
            fontSize: ' 0.9em',
          },
        },
      },
    },
    /* end: change outline fiels label text size */

@pailas
Copy link

pailas commented Oct 31, 2021

Thank you @sebascomeau, your solution for v5 worked for me.

@slim-hmidi
Copy link
Contributor

I'm facing this issue when I update the font-size and font-weight and using Futura-Bt medium fonts.
If the label contains a single or small word it is displayed correctly. But if it is composed label of 2 or more words, there is no space between the border and the label.
I tried to add the some padding for the legend label but it does not work. The legend width should fit the label input width in order to add the padding and does not add extra space at the end of the word.
How can I fix this issue with customized font-size?

@slim-hmidi
Copy link
Contributor

I tried to set the width for the legend when I changed the font-family and font-size using this:

width: `${label.trim().length * 8 * 0.75}px `

But I'm not sure that the width is calculated correctly.
Is there any util function that fits the different font-family and sizes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: text field This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants