在定义 @font-face
的 CSS 中,如果浏览器解析到该规则,它会立即尝试加载指定的字体文件,而不等待 JavaScript 的执行。这意味着在没有调用 JavaScript(如 Font Face Observer)之前,浏览器会自动加载 @font-face
中定义的字体。
为了确保字体在 JavaScript 控制下延迟加载,可以采取以下措施:
- 将
@font-face
定义移动到 JavaScript 执行之后。 - 使用 Font Face API 动态加载字体。
方法 1:将 @font-face
定义移动到 JavaScript 执行之后
可以在 JavaScript 执行后动态插入 @font-face
定义。以下是示例代码:
步骤 1:移除全局CSS中的 @font-face
定义
从 styles/global.css
中移除 @font-face
定义。
步骤 2:在 JavaScript 中动态插入 @font-face
在 _app.js
中使用 JavaScript 动态插入 @font-face
规则:
// pages/_app.js
import { useEffect } from 'react';
import '../styles/global.css';
import FontFaceObserver from 'fontfaceobserver';
function MyApp({ Component, pageProps }) {
useEffect(() => {
const robotoFont = new FontFaceObserver('Roboto');
robotoFont.load().then(() => {
const style = document.createElement('style');
style.innerHTML = `
@font-face {
font-family: 'Roboto';
src: url('/fonts/Roboto-Regular.woff2') format('woff2'),
url('/fonts/Roboto-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
}
html.roboto-loaded body {
font-family: 'Roboto', sans-serif;
}
`;
document.head.appendChild(style);
document.documentElement.classList.add('roboto-loaded');
}).catch((error) => {
console.error('Roboto font failed to load:', error);
});
}, []);
return <Component {...pageProps} />;
}
export default MyApp;
方法 2:使用 Font Face API 动态加载字体
使用 Font Face API 直接在 JavaScript 中加载字体:
// pages/_app.js
import { useEffect } from 'react';
import '../styles/global.css';
function MyApp({ Component, pageProps }) {
useEffect(() => {
const font = new FontFace('Roboto', 'url(/fonts/Roboto-Regular.woff2)', {
weight: '400',
style: 'normal',
});
font.load().then((loadedFont) => {
document.fonts.add(loadedFont);
document.documentElement.classList.add('roboto-loaded');
}).catch((error) => {
console.error('Roboto font failed to load:', error);
});
}, []);
return <Component {...pageProps} />;
}
export default MyApp;
在这种方法中,浏览器在 JavaScript 执行后才会尝试加载字体。
全局 CSS
无论使用哪种方法,全局 CSS 都可以定义字体回退和加载后的字体应用:
/* styles/global.css */
body {
font-family: sans-serif; /* Fallback font */
}
html.roboto-loaded body {
font-family: 'Roboto', sans-serif;
}
综述
通过将 @font-face
定义动态插入或使用 Font Face API,你可以控制字体的加载时机,从而避免浏览器在 JavaScript 执行之前自动加载字体文件。选择合适的方法可以根据项目需求来决定。