是否可以在页面加载之前预加载或以其他方式缓存 @font-face 字体,最有可能是使用 javascript,这样当页面最终加载时,您就不会出现丑陋的跳转?
14 回答
自 2017 年以来,您已预加载
MDN:元素的 rel 属性的 preload 值允许您在 HTML 中编写声明性获取请求,指定页面在加载后很快需要的资源,因此您希望在页面加载生命周期的早期开始预加载,之前浏览器的主要渲染机制启动。这确保了它们更早地可用并且不太可能阻止页面的第一次渲染,从而提高性能。
<link rel="preload" href="/fonts/myfont.eot" as="font" crossorigin="anonymous" />
始终检查浏览器兼容性。
它对于字体预加载最有用(不等待浏览器在某些 CSS 中找到它)。您还可以预加载一些徽标、图标和脚本。
- 此处讨论了其他技术的优缺点(不是我的博客)。
- 另请参阅prefetch (similar) 和 SO question about preload vs prefetch。
一种简单的技术是将其放在索引中的某个位置:
<div class="font_preload" style="opacity: 0">
<span style="font-family: 'myfontface#1font-family', Arial, sans-serif;"></span>
<span style="font-family: 'myfontface#2font-family', Arial, sans-serif;"></span>
...
</div>
在 Chrome 34、Safari 7 和 FF 29 和 IE 11 上测试
这里有一些“预加载”技术:http: //paulirish.com/2009/fighting-the-font-face-fout/
主要是欺骗浏览器尽快下载文件..
您还可以将其作为 data-uri 提供,这很有帮助。您还可以隐藏页面内容并在准备好时显示它。
你的 head 应该包括如下的预加载 rel:
<head>
...
<link rel="preload" as="font" href="/somefolder/font-one.woff2">
<link rel="preload" as="font" href="/somefolder/font-two.woff2">
</head>
这样,支持预加载的浏览器将预加载 woff2,并且所有后备格式都将像往常一样加载。
你的 css 字体看起来应该和这个类似
@font-face {
font-family: FontOne;
src: url(../somefolder/font-one.eot);
src: url(../somefolder/font-one.eot?#iefix) format('embedded-opentype'),
url(../somefolder/font-one.woff2) format('woff2'), //Will be preloaded
url(../somefolder/font-one.woff) format('woff'),
url(../somefolder/font-one.ttf) format('truetype'),
url(../somefolder/font-one.svg#svgFontName) format('svg');
}
@font-face {
font-family: FontTwo;
src: url(../somefolder/font-two.eot);
src: url(../somefolder/font-two.eot?#iefix) format('embedded-opentype'),
url(../somefolder/font-two.woff2) format('woff2'), //Will be preloaded
url(../somefolder/font-two.woff) format('woff'),
url(../somefolder/font-two.ttf) format('truetype'),
url(../somefolder/font-two.svg#svgFontName) format('svg');
}
避免 FOIT:不可见文本的闪烁
当然,第一步是在 HTML 中预加载字体:
<link rel="preload" href="pacifico.woff2" as="font" crossorigin="anonymous">
请注意,字体总是在启用跨域资源共享 (CORS) 的情况下预加载,即使字体位于同一服务器上:
当预加载启用 CORS 获取的资源时(例如 fetch()、XMLHttpRequest 或字体),需要特别注意设置元素的 crossorigin 属性。该属性需要设置为匹配资源的 CORS 和凭据模式,即使获取不是跨域的。
因此,该crossorigin="anonymous"
属性是绝对必要的。
type="MIME-type"
关于可选属性不能说同样的话。浏览器和机构之间对于MIME 类型字体应该是什么存在很大分歧。如果为某个浏览器声明了错误的类型,字体文件将不会被预加载。因此,最好不要type="MIME-type"
一起使用 HTML 属性。
然后,就是酷孩子所说的 FOIT;无形文字的闪光。在现代浏览器中,可以通过将属性添加到CSS 声明来轻松避免这种 FOIT。font-display: swap;
@font-face
@font-face {
font-family: 'Pacifico';
font-style: normal;
font-weight: 400;
src: local('Pacifico Regular'), local('Pacifico-Regular'), url(pacifico.woff2) format('woff2');
font-display: swap;
}
此答案不再是最新的
请参考这个更新的答案:https ://stackoverflow.com/a/46830425/4031815
已弃用的答案
我不知道当前有任何技术可以避免字体加载时闪烁,但是您可以通过为您的字体发送适当的缓存标头并确保该请求尽快通过来将其最小化。
正确的字体预加载是 HTML5 规范中的一个大漏洞。我已经经历了所有这些事情,我发现最可靠的解决方案是使用 Font.js:
http://pomax.nihongoresources.com/pages/Font.js/
您可以使用与加载图像相同的 API 来加载字体
var anyFont = new Font();
anyFont.src = "fonts/fileName.otf";
anyFont.onload = function () {
console.log("font loaded");
}
它比Google 笨重的 Webfont Loader更简单、更轻量级
这是 Font.js 的 github 存储库:
通过 Google 的webfontloader
var fontDownloadCount = 0;
WebFont.load({
custom: {
families: ['fontfamily1', 'fontfamily2']
},
fontinactive: function() {
fontDownloadCount++;
if (fontDownloadCount == 2) {
// all fonts have been loaded and now you can do what you want
}
}
});
我发现最好的方法是预加载包含字体的样式表,然后让浏览器自动加载它。我在其他位置(在 html 页面中)使用了 font-face,但随后我可以简单地观察字体更改效果。
<link href="fonts.css?family=Open+Sans" rel="preload stylesheet" as="style">
然后在 font.css 文件中,指定如下。
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'),
url('open-sans-v16-latin-regular.woff2') format('woff2'); /* Super Modern Browsers */
}
当通过链接标签预加载字体时,您无法为字体分配名称(如果我错了,请纠正我我还没有找到方法),因此您必须使用 font-face 将名称分配给字体。尽管可以通过链接标签加载字体,但不建议这样做,因为您不能使用它为字体指定名称。如果没有 font-face 的名称,您将无法在网页的任何地方使用它。根据 gtmetrix,样式表在开头加载,然后按顺序加载其余脚本/样式,然后加载 dom 之前的字体,因此您看不到字体更改效果。
我通过在我的主文档中添加一些字母并使其透明并分配我想要加载的字体来做到这一点。
例如
<p>normal text from within page here and then followed by:
<span style="font-family:'Arial Rounded Bold'; color:transparent;">t</span>
</p>
这应该可以解决您的问题。
回答您最初的问题:是的,您可以。目前只有 Gecko 和 WebKit 浏览器支持它。
您只需要在头脑中添加链接标签:
<link rel="prefetch" href="pathto/font">
<link rel="prerender" href="pathto/page">
使用标准的CSS 字体加载 API。
等待(全部)字体加载,然后显示您的内容:
document.fonts.ready.then((fontFaceSet) => {
console.log(fontFaceSet.size, 'FontFaces loaded.');
document.getElementById('waitScreen').style.display = 'none';
});
最近我正在开发一个与 CocoonJS 兼容的游戏,其 DOM 仅限于 canvas 元素 - 这是我的方法:
将 fillText 与尚未加载的字体一起使用将正确执行但没有视觉反馈 - 因此画布平面将保持不变 - 您所要做的就是定期检查画布是否有任何更改(例如循环通过 getImageData 搜索任何非透明像素),当字体正确加载时会发生这种情况。
我在最近的文章http://rezoner.net/preloading-font-face-using-canvas,686中对这种技术进行了更多解释
谷歌为此提供了一个不错的库:https ://developers.google.com/webfonts/docs/webfont_loader 您可以使用几乎任何字体,并且该库会将类添加到 html 标记。
它甚至会在加载和激活某些字体时为您提供 javascript 事件!
不要忘记提供压缩后的字体文件!它肯定会加快速度!