等待字体加载,然后渲染网页


69

我正在使用@ font-face将字体嵌入到我的网站中。首先,文本呈现为系统默认值,然后(假定字体文件已加载)正确的字体将在几分之一秒后呈现。有没有一种方法可以通过延迟页面渲染直到加载字体或类似字体之后来最小化/消除此延迟。


缓存字体将起作用。
克里

请记住,这是使您的网站看起来非常慢的好方法,因为无线链接上的用户可能需要一段时间才能加载Web字体。如果文本在几秒钟内不显示,许多用户只会点击后退按钮。
erjiang 2015年

这回答了你的问题了吗?网络字体加载后如何通知
Zach Saucier

Answers:


22

这取决于浏览器的行为方式。

首先,您的@font在哪里声明?它是内联到HTML,是在页面上的CSS表单中声明,还是(希望)在外部CSS表单中声明?

如果不在外部工作表中,请尝试将其移动到一个工作表中(通常还是最好的做法)。

如果这样做没有帮助,您需要问自己:秒差的一小部分是否真的对用户体验造成重大损害吗?如果是这样,请考虑使用JavaScript,您可能可以执行一些操作,重定向,暂停等操作,但实际上这些操作可能比原始问题更糟糕。对用户来说更糟,而维护则更糟。

该链接可能有帮助:

http://paulirish.com/2009/fighting-the-font-face-fout/


1
最好的办法是遵循Tom的建议,此外,请确保您的客户端在后续页面加载时不会访问Web服务器,因为这是一个真正的字体呈现阻止程序-为CSS文件设置一个过期标头,并大声疾呼一本关于实际的字体资源,对您来说不错。
FilipDupanović

不错的文章。希望Firefox在不远的地方采用safari方法加载字体。过去,FOUT对我来说不是问题,但是对于当前站点,我使用的自定义字体与任何系统字体都大不相同,因此第一次出现了非常明显的闪光。
wheresrhys 2011年

1
大字体(即200 Kb)和慢速连接(即3G)不是几分之一秒。对于使用SIM卡芯片的平板电脑,设计人员应考虑这种情况。
Jaime

27

编辑:最好的方法可能是base64编码您的字体。这意味着在解析和显示HTML时必须完全加载字体。您可以使用字体squirrel的webfont生成器https://www.fontsquirrel.com/tools/webfont-generator来执行此操作,方法是单击“专家”,然后单击“ base64编码”。这就是TypeKit之类的服务的工作方式。


原始答案: 检测字体是否已加载的另一种方法是使用FontLoader https://github.com/smnh/FontLoader或复制其策略。

它们绑定到浏览器中的scroll事件,因为加载字体时,它将调整文本的大小。它使用两个包含div(当高度变化时将滚动)和IE的单独后备。

一种替代方法是setInterval使用定期检查DOM ,但使用javascript事件则更快,更优越。

显然,您可以执行一些操作,例如将body的不透明度设置为0,然后在字体加载后将其显示出来。


3
我真的很喜欢base64解决方案!为我工作!
克里斯

17

由于没有人提到,我认为这个问题需要更新。我设法解决此问题的方法是使用现代浏览器支持的“预加载”选项。

如果有人不需要支持旧的浏览器。

<link rel="preload" href="assets/fonts/xxx.woff" as="font" type="font/woff" crossorigin>

一些有用的链接以及更多详细信息:

https://developer.mozilla.org/zh-CN/docs/Web/HTML/Preloading_content http://www.bramstein.com/writing/preload-hints-for-web-fonts.html


这是最好的答案,自定义字体不使用时不会加载。这个立即加载,因此第一次使用字体时不会显示框字体
Jones G


4

这段代码对我来说非常有效。它使用Font Loading API,该API在现代浏览器中具有良好的支持。

<style>
  @font-face {
    font-family: 'DemoFont';
    font-style: normal;
    font-weight: 400;
    src: url("./fonts/DemoFont.eot");
    src: url("./fonts/DemoFont.woff2") format("woff2"),
    url("./fonts/DemoFont.woff") format("woff"),
    url("./fonts/DemoFont.ttf") format("truetype");
  }

  .font {
    font-family: 'DemoFont';
    color: transparent;
  }

  html.font-loaded .font {
    color: inherit; // Override `transparent` from .font
  }

</style>
<script>
  // Check if API exists
  if (document && document.fonts) {    
    // Do not block page loading
    setTimeout(function () {           
      document.fonts.load('16px "DemoFont"').then(() => {
        // Make font using elements visible
        document.documentElement.classList.add('font-loaded') 
      })
    }, 0)
  } else {
    // Fallback if API does not exist 
    document.documentElement.classList.add('font-loaded') 
  }
</script>

技巧是将使用字体的元素的CSS颜色设置为透明。加载后,可通过将font-loadedclass添加到<html>element来重置。

请替换DemoFont为对您的项目有意义的东西,以使其正常工作。


1
一个问题是,它fonts.load('10px Nothing')会很高兴地用一个空字体列表解决。您需要结合loadcheck
蓬松的

3

只有IE首先加载字体,然后再加载页面的其余部分。其他浏览器由于某种原因并发加载。想象一下,托管字体的服务器或字体下载存在问题。您将挂起整个网站,直到加载字体。在我看来,闪过无样式的文字总比根本看不到该网站好


3
好吧,除了在同一网站上托管字体时。
劳伦斯·多尔

3
此外,除了当字体是引导字形图标
乔希Sutterfield

4
此外,除非您需要知道字形的像素大小。
大卫

3
flash of unstyled text使您的用户认为您(创作者)在工作上不专业,并且该应用程序中存在某些故障。这是UX人。
AmirHossein '18

3

您可以在@ font-face内使用CSS字体显示。所有可用值的关键字为:

  • 汽车
  • 交换
  • 倒退
  • 可选的

Giulio Mainardi写了一篇很好的文章,关于所有这些,您应该在sitepoint上使用它。

您可以在这里阅读:https : //www.sitepoint.com/css-font-display-future-font-rendering-web/?utm_source=frontendfocus&utm_medium=email


这是在2020年完成此操作的正确且首选的方法。不要因为用户连接不稳定而惩罚用户,而是font-display: block确实需要时使用。绝对不要执行Ryan Taylor建议的操作,并且对base64进行编码。没有用户愿意再下载30%的数据,这样您就可以阻止渲染,直到下载完成为止(即使是,尤其是在移动连接上),即使仅仅是“例如” 300kB的问题。
吉万·帕尔


2

在渲染到HTML画布时遇到了类似的问题,这是我的解决方案。它基于FontFace API,与Holtwicks方法类似。主要区别在于,这是一种通用方法,对于外部字体/样式表(例如Google字体)而言,它是开箱即用的。

一些注意事项; fonts.load( ... )如果尚不知道该字体,它将愉快地使用一组空字体进行解析。据推测,如果在添加字体的样式表之前调用此代码,就会发生这种情况。我添加了一个fonts.check(...)以克服这一点。

这样一来,您就可以等待JavaScript执行,直到找到可用的字体为止,因此对于“常规” HTML内容,它不会立即可用。您可以将其与上述Holtwicks答案结合使用。

export async function waitForFontLoad(
    font: string,
    timeout = 1000,
    interval = 10
) {
    return new Promise((resolve, reject) => {
        // repeatedly poll check
        const poller = setInterval(async () => {
            try {
                await document.fonts.load(font);
            } catch (err) {
                reject(err);
            }
            if (document.fonts.check(font)) {
                clearInterval(poller);
                resolve(true);
            }
        }, interval);
        setTimeout(() => clearInterval(poller), timeout);
    });
}

-4
(function() {
        document.getElementsByTagName("html")[0].setAttribute("class","wf-loading")
        document.getElementsByTagName("html")[0].setAttribute("className","wf-loading")
    })();

使用此方法..与Webfont.js一起使用


-6

也许是这样的:

$("body").html("<img src='ajax-loader.gif' />");

然后,当页面加载时,将正文内容替换为实际内容,并希望使用完全渲染的字体,尽管如此,您可能仍需要尝试一下...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.