在呈现网页之前等待加载字体

whe*_*hys 55 css fonts font-face

我正在使用@ font-face在我的网站中嵌入字体.首先,文本呈现为系统默认值,然后(一旦字体文件可能已加载),正确的字体稍后呈现一小段时间.有没有办法最小化/摆脱这种延迟,通过延迟页面渲染,直到字体加载或类似.

Thi*_*ura 30

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

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

<link rel="preload" href="assets/fonts/xxx.woff" as="font" type="font/woff" crossorigin>
Run Code Online (Sandbox Code Playgroud)

一些包含更多详细信息的有用链接:

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

  • 这将预加载字体并使其在 DOM 渲染时可用。但是,由于它不是阻塞的,因此仍然无法保证在页面渲染之前加载自定义字体。 (6认同)
  • 这是最好的答案,自定义字体在尚未使用时不会加载。这个会立即加载它,因此第一次使用字体时不会出现框字体 (3认同)

Tom*_*len 18

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

首先,你的@font声明在哪里?它是否与您的HTML内联,在页面上的CSS工作表中声明,或者(希望)在外部CSS工作表中声明?

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

如果这没有帮助,你需要问自己是第二个差异的一小部分真的显着不利于用户体验?如果是,那么考虑JavaScript,你可以做一些事情,重定向,暂停等,但这些可能实际上比原来的问题更糟糕.对用户来说更糟糕,更糟糕的是维护.

此链接可能有所帮助:

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


Rya*_*lor 15

编辑:最好的方法可能是base64编码你的字体.这意味着您的字体必须在解析和显示HTML时完全加载.您可以使用font squirrel的webfont生成器https://www.fontsquirrel.com/tools/webfont-generator通过单击"Expert"然后单击"base64 encode"来执行此操作.这就是TypeKit等服务的工作原理.


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

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

另一种方法是定期检查DOM setInterval,但使用javascript事件要快得多且优越.

显然,你可以做一些事情,比如将body的不透明度设置为0,然后在字体加载后显示它.

  • 我真的很喜欢base64解决方案!为我工作! (3认同)

Hol*_*ick 8

这段代码对我来说非常有效。它使用在现代浏览器中得到良好支持的字体加载 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>
Run Code Online (Sandbox Code Playgroud)

技巧是将使用该字体的元素的 CSS 颜色设置为透明。font-loaded加载后,通过向元素添加类来重置它<html>

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

  • 这样做的一个问题是 `fonts.load('10px Nothing')` 会很高兴地用一个空的字体列表来解析。您需要结合“load”和“check”。 (2认同)

Flu*_*ffy 6

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

一些注释; 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);
    });
}
Run Code Online (Sandbox Code Playgroud)


dav*_*ave 5

Joni Korpi有一篇关于在页面其余部分之前加载字体的文章.

http://jonikorpi.com/a-smoother-page-load/

他还使用了loading.gif来缓解延迟,因此用户不会感到沮丧.


Lir*_*nna 5

您可以在 @font-face 中使用 CSS font-display。所有可用值的关键字是:

  • 汽车
  • 堵塞
  • 交换
  • 倒退
  • 选修的

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建议的](/sf/answers/1665635891/)并对任何内容进行base64编码;没有用户希望必须下载 30% 以上的数据,以便您可以阻止渲染直到下载完成,即使(不,*特别是*,在移动连接上)如果它“仅”是 300kB 的问题。 (2认同)