Reputation: 77
I'm trying to include a custom font in my React app (made with create-react-app). It seems to be somewhat working but only after 2-3 second after loading the page. Until then, the text appears to use the browser's default font (like Times New Roman), and then swaps to the custom font after a few seconds. Can someone please explain to me why this is happening and what I need to do to fix this?
I'm importing the font into my top-level App.js
file like so:
import './fonts/tarrgetital.ttf';
import './App.scss';
And have it declared in my App.scss
file like so:
@font-face {
font-family: 'tarrgetital';
src: local('tarrgetital'), url(./fonts/tarrgetital.ttf) format('truetype');
}
h2 {
font-family: tarrgetital;
}
Upvotes: 5
Views: 11655
Reputation: 4701
Use document.fonts.load
with useEffect
import React, { useEffect, useState } from 'react';
const MyComponent = () => {
const [loading, setLoading] = useState(true);
useEffect( ()=> {
document.fonts.load("12px Font-Name").then( () => { setLoading(false) } );
}, [])
return (
<React.Fragment>
{ loading
? <div> Loading... </div>
: <main> Rest of Elements </main>
}
</React.Fragment>
);
};
export default MyComponent;
Upvotes: 0
Reputation: 675
I use also font-face on index.css file
@font-face {
font-family: "Avenir";
src: local("Avenir"),
url("assets/fonts/AvenirNextLTPro-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
<link rel="stylesheet" href="../src/index.css" />
Then I imported index.css file into index.html, this worked for me.
Upvotes: 0
Reputation: 178
One alternative is to use webfontloader. It was co-developed by Google and Typekit.
npm i webfontloader
In your App.js file add this one. Note: You still have to maintain your font face declarations at your css file.
import WebFont from 'webfontloader';
WebFont.load({
custom: {
families: ['tarrgetital'],
},
});
Upvotes: 0
Reputation: 915
The delay in loading the web fonts is an expected behaviour issue and it's happening because the browser load the fonts when it detects a DOM element with a CSS selector that matches the font-face rule and that happens when then HTML file and all the CSS files have been downloaded on the client. It's a lazy loading mechanism. There are some solutions to improve this behavior:
Use optimized web font file:
For better performance, you can swap your TTF
font file in the
font-face with the woff
and woff2
file formats. these formats are
compressed in gzip thus reducing the file size and initial
downloading time on the client. If those formats are not available
you can use one of many online tools to convert the font file (google
TTF to woff2
).
Webpack Preload:
In webpack 4.6.0+ you can preload modules. this uses
the preload
hint in HTML link tags (<link rel="preload">
). it will tell the browser to preload the resource before downloading the rest of the resources. To use this option replace import './fonts/tarrgetital.ttf';
with import(/* webpackPreload: true */ './fonts/tarrgetital.ttf');
More on webpack preload here: https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules and more info on HTML preload hint here: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
Upvotes: 10