I’m working in javascript and am applying the Material Icons fontFamily to my component. On the initial render, the child component is being rendered as normal text using what I would assume is the browser’s default fallback font. Once the font has loaded, then it re-renders as an icon. I want to set this up so that nothing is displayed at all until the font has been loaded. I have normal text to the right of the icon that makes leaving the text present for accessibility an invalid argument.
Here are a couple of screenshot for reference:
Here is the code as it is now, where iconName is the text being used to render my icon:
<div
className="text-left d-flex align-items-center"
style={{
fontFamily: "Material Icons",
fontSize: "24px",
opacity: parentActive || parentExpanded ? 1 : 0.8,
padding: "0 9px",
maxWidth: "45px",
overflow: "hidden",
height: "2.5rem",
color:
parentActive || parentExpanded
? color.primary
: undefined,
}}
>
<span aria-hidden>{iconName}</span>
</div>
I have tried a few different solutions but only one them has sort of worked and am looking for a better alternative if possible. One solution that I tried was to use a ternary operation to render a blank space when the font is not yet loaded:
{document.fonts.check('1em "Material Icons"') ?
<div
className="text-left d-flex align-items-center"
style={{
fontFamily: "Material Icons",
fontSize: "24px",
opacity: parentActive || parentExpanded ? 1 : 0.8,
padding: "0 9px",
maxWidth: "45px",
overflow: "hidden",
height: "2.5rem",
color:
parentActive || parentExpanded
? color.primary
: undefined,
}}
>
<span aria-hidden>{iconName}</span>
</div>
: <div style={{ width: "42px", height: "40px", color: "transparent" }}/>
}
This solution does work, but there is an issue with that I would like to avoid. With my original code, once the font has been loaded and you reload the page manually, the icon is loaded initially since the font has already loaded. With this new code snippet, it does avoid rendering the text when the font family has not yet been loaded at the initial render. The issue now is that it always initializes to false for some amount of time before seeing that the font is there. Running this code next to the original code at the same time shows that the icon can sometimes be rendered right away whereas this conditional statement doesn’t allow that to happen.
Another idea that I am aware of is using the font-display property and setting it to block. I think this would work, but I can’t figure out how to apply it to my code. It seems that webpack in my project is not configured to be able to read @font-face from a css file and I haven’t seen any other way to do this. I also am not sure what to put for the font-family src since I didn’t need to specify the src in the div styles before. I put questions marks in here but when I tried it I just removed the line entirely.
@font-face {
font-family: 'Material Icons';
src: ??;
font-display: block;
}
.material-icons {
font-family: 'Material Icons', sans-serif;
}
I get an error in the browser when I try to do this:
ERROR in ./src/navigation/components/iconFont.css 1:0 Module parse failed: Unexpected character ‘@’ (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > @font-face { | font-family: ‘Material Icons’;
I don’t want to have to update the project configurations to get that approach to work. Does anyone have any ideas that I could try out? Any help is much appreciated!