网页字体加载怎么优化?FOIT、FOUT和font-display的机制与实战

网页字体加载怎么优化?FOIT、FOUT和font-display的机制与实战
张文保 15 分钟阅读 4,189 阅读
本文目录
  1. FOIT和FOUT到底是什么?字体没加载完时页面在闹哪样?
  2. 我那个出海品牌站的标题,为什么加载时空白三秒?
  3. font-display到底怎么控制这个行为?五个值分别什么脾气?
  4. 字体换入为什么会引起布局跳动?它和CLS什么关系?
  5. size-adjust和度量覆盖,怎么让字体换入不跳动?
  6. 字体文件怎么瘦身、怎么快点到场?
  7. 可变字体能帮上字体优化的忙吗?
  8. 自托管字体和用第三方字体服务,到底该选哪个?
  9. 品牌站那个标题,最后怎么做到秒显不跳?
  10. 常见问题解答
  11. font-display到底该设swap还是optional?
  12. 不设font-display会怎么样?
  13. preload字体是不是加了就一定好?
  14. 中文字体这么大,网页字体优化还有救吗?
  15. size-adjust这些度量覆盖,浏览器支持度够吗?
  16. 字体加载慢,会直接影响SEO排名吗?
  17. 权威参考资料

摘要:网页字体加载慢,会闹出两种幺蛾子:字体没到位时文字干脆不显示,叫FOIT(隐形文字闪烁);或者先拿后备字体顶上、字体一到又换回来,叫FOUT(无样式文字闪烁)。控制这个行为的开关是CSS的font-display,五个取值各有脾气。更麻烦的是字体换入那一下,后备字体和正式字体尺寸对不齐,会把整段文字挤得重排、连带引发布局偏移。这篇把FOIT、FOUT、font-display的机制讲透,再给一套让字体又快到场、又不跳动的落地做法。

我是保哥,做SEO二十多年,海外独立站经手不少。字体这东西,平时没人拿它当回事——不就是个好看嘛。可一旦碰上海外弱网,它就能让你的标题在用户眼前空白三秒,或者在内容刚读一半时突然整段抽动一下。今天就聊聊这个最不起眼、却最容易毁掉首屏观感的家伙:网页字体加载。它不像图片那么显眼,出问题时也不报错,却能在用户对你的站产生第一印象的那零点几秒里,悄悄扣分。

这篇会把字体加载的两种翻车形态、控制它的font-display开关、以及它和布局偏移的暧昧关系一次讲清楚,最后给你一套能直接抄的优化配方。

FOIT和FOUT到底是什么?字体没加载完时页面在闹哪样?

网页用自定义字体,得先把字体文件从网上下载下来。可下载要时间,这段时间里文字怎么办?浏览器有两种应对,对应两种翻车形态。

一种叫FOIT,隐形文字闪烁。浏览器决定:字体没下完,那这段文字干脆先别显示,等字体到了再一起亮出来。结果就是用户盯着一片空白,标题、正文都不见踪影,字体一到才唰地冒出来。网速慢时,这段空白能长达好几秒,用户还以为页面坏了。

另一种叫FOUT,无样式文字闪烁。浏览器决定:先拿系统里的后备字体把文字显示出来,别让用户干等,等自定义字体下完了再换上去。好处是内容立刻可读,坏处是字体切换那一下,字形、字宽一变,文字会明显地闪跳一下。CSS-Tricks对FOUT、FOIT几种字体加载形态的对比里,把这几种取舍的来龙去脉讲得很透。

我那个出海品牌站的标题,为什么加载时空白三秒?

说个真事。前两年一个做时尚配饰的品牌客户找我,说他们的独立站在欧美用户那儿口碑不错,可有些用户反馈打开页面时,大标题会先空一截、过一两秒才蹦出来,显得很廉价。他们设计师较真,非说是字体的锅,但查不出原因。

我一看代码就明白了:他们用了一款很漂亮的品牌字体,通过第三方字体服务托管,没设font-display。浏览器默认走的是接近block的行为——字体没下完,标题文字一律隐形。偏偏这款字体文件不小,海外用户网络一波动,那个隐形期就拉到两三秒。用户看到的,就是一个迟迟不肯露面的空标题。

我当时给设计师做了个对比实验,让他自己拿手机开着弱网打开页面:那个空白期长得让人以为页面卡死了,好几秒里屏幕上就是一块干净的留白,等字体加载完,标题才慢悠悠地浮现。设计师看完自己就服气了——原来毁掉高级感的不是字体不够美,而是它来得太晚。用户没耐心陪一个空标题干等,很多人在标题露面之前就已经划走了。

更糟的是,等字体终于加载完、标题冒出来,因为它比后备字体宽、行高也不同,底下的副标题和按钮又被顶下去一点。既有FOIT的空白,又在结尾补了一刀布局跳动。设计师想要的高级感,全被这一空一跳给毁了。

font-display到底怎么控制这个行为?五个值分别什么脾气?

治这种病的核心开关,是CSS里 @font-face规则中的font-display属性。它规定了字体加载期间和加载完之后,浏览器该怎么对待文字。按 MDN对font-display属性的定义,它有五个取值,脾气各不相同。

  • auto:把决定权交给浏览器,大多数浏览器的默认行为接近block,也就是倾向于FOIT。不设font-display,通常就是这个效果。
  • block:给一个短暂的隐形期(约3秒),期间文字隐形等字体;超时了才用后备字体顶上,字体到了再换。追求品牌字体绝对精准的场景会用它,代价是可能的空白。
  • swap:几乎不隐形,立刻用后备字体显示文字,自定义字体一到马上换。内容第一时间可读,代价是明显的FOUT闪跳。这是最常用的值。
  • fallback:折中款。极短的隐形期(约100毫秒),之后用后备字体;但只给字体很短的换入窗口,错过了这次就一直用后备字体。平衡观感和稳定。
  • optional:最克制。极短隐形期后用后备字体,且字体这次没及时到就干脆不换了,留到下次访问(缓存命中)再用。它几乎不会引起布局跳动,特别适合在意CLS的场景。

怎么选?如果你最怕的是空白,用swap;如果你最怕的是跳动,用optional;如果你对品牌字体的精准度有洁癖、又能接受短暂空白,才考虑block。大多数站,swap或optional二选一就够了。

我个人的偏好是:正文和大段文字用swap,保证内容第一时间可读,读的人不会因为等字体而流失;而那些不影响阅读、纯装饰性的字体,比如某个花哨的引言体,用optional,宁可这次用不上也别让它跳。把字体按重要性分级对待,比全站一刀切设同一个值要聪明得多。这跟做菜一个道理,主菜和配菜的火候不能一样。

字体换入为什么会引起布局跳动?它和CLS什么关系?

这里得把字体和布局偏移的关系挑明。你用swap,内容是立刻可读了,可后备字体(比如系统的Arial)和你的品牌字体,字宽、字高、行高往往对不齐。字体一换,同样一段话占的空间变了,行数可能都不一样,底下的内容跟着被推上推下——这就是一次布局偏移,会实打实地计进CLS。

所以字体优化和视觉稳定性是一根绳上的蚂蚱。我在 资源提示技术怎么给关键资源提速里讲的preload,能让字体早点到场、缩短后备字体露脸的时间,从而减少换入时的跳动幅度。但光靠preload还不够——字体总归有加载时间,只要发生了换入,度量对不齐就会跳。

真要根治,得让后备字体和正式字体的度量尽量对齐,让换入前后占的空间一样大。这就引出了下一个主角:字体度量覆盖。字体加载对文字LCP也有影响,如果你的最大内容块正好是一段大标题文字,字体迟迟不到,这块内容的LCP就被拖慢,这条线我在 六层架构把LCP从四秒压到一秒半里也提到过。

size-adjust和度量覆盖,怎么让字体换入不跳动?

现代浏览器给了一组很好用的 @font-face描述符,专门用来对齐后备字体和正式字体的度量:size-adjust、ascent-override、descent-override、line-gap-override。

思路是这样的:你给后备字体单独定义一个 @font-face,用这几个描述符把它的字号缩放比例、上沿、下沿、行间距,调到跟正式字体几乎一致。这样在字体换入的前一刻,后备字体占的空间就已经和正式字体一模一样了,等正式字体一到,无缝替换,文字纹丝不动,布局偏移趋近于零。Chrome团队对用度量覆盖消除字体换入跳动的讲解里,给了具体怎么算这几个值的方法。

手工算这些值有点烦,好在有工具能自动生成。一些现代前端框架的字体方案,已经内置了自动生成度量对齐后备字体的能力,你几乎不用操心。web.dev对字体加载最佳实践的汇总里,把preload、font-display、度量覆盖这几件事怎么配合,串成了一套完整流程,值得照着搭。

字体文件怎么瘦身、怎么快点到场?

再快的策略,也架不住字体文件本身又肥又慢。所以优化字体,另一条腿是给文件瘦身、让它早到。

第一,用WOFF2格式。它是目前压缩率最高的网页字体格式,比老的TTF、WOFF小一大截,现代浏览器全支持,没理由不用。第二,做字体子集化(subset)。一款中文字体动辄几MB,可你页面上其实只用到几百个字;把用不到的字符剔掉、只留用得上的,体积能砍到零头。Smashing Magazine对用描述符和子集化降低字体加载影响的实操里,把这些手段的收益量化得很清楚。

第三,给关键字体加preload,让浏览器早早并行地把它拉下来,别等解析到用它的CSS才开始下载。第四,尽量自托管字体,别让浏览器为了拿字体多跟一个第三方域名握手。这几招叠一块,字体到场的时间能大幅提前,FOIT、FOUT的窗口自然就短了。

当然,字体到场快不快,还有个前提是服务器本身响应得够快——字体文件走的也是网络请求,服务器慢、缓存没配好,字体照样迟到。怎么把服务器响应和多层缓存一起理顺,我在 TTFB与多层缓存怎么一起治里从头到尾拆过,那套地基打牢了,字体这类静态资源的到场速度也跟着水涨船高。

可变字体能帮上字体优化的忙吗?

顺带说个进阶话题:可变字体(variable fonts)。传统做法里,你要粗体、细体、斜体,就得分别加载好几个字体文件,一个字重一个文件,加载和管理都费劲。可变字体把这些变化装进了一个文件里,用一个文件就能覆盖从最细到最粗的所有字重,甚至还能做无级的中间值。

对性能的意义在于:如果你的设计确实用到了多个字重,可变字体往往比分别加载多个静态字体文件更省。少了好几次网络请求,管理也简单。但它不是无脑更优——要是你整站其实只用一个字重,那单独一个静态字体文件反而更小、更快。所以别为了时髦而上可变字体,先看你到底用了几个字重,用得多才划算。

还有一点得留神:可变字体单个文件通常比单个静态字重要大,因为它把所有变化都打包了。所以它的账要整体算——用三四个字重时它稳赚,只用一个字重时它反而吃亏。做子集化时,可变字体同样适用,该剔的字符照剔。

自托管字体和用第三方字体服务,到底该选哪个?

这是个老争论。用第三方字体服务(比如某知名字体托管)省事,一行代码就搞定,还蹭人家的CDN。但代价有几个:多一次跨域名的DNS解析和连接握手,拖慢字体到场;受制于第三方的可用性和速度;某些地区访问第三方还可能不稳。

自托管则是把字体文件放到自己服务器(或自己的CDN)上。好处是少一次第三方握手、字体和页面同源、加载更可控,还顺带规避了把用户信息暴露给第三方的隐私顾虑。近几年的主流建议,是能自托管就自托管。Google Fonts官方知识库对用font-display加载网页字体的说明里,也大方给出了自托管的下载方式和用法,不再强推挂它的域名。

我那个品牌客户,最后就是走的自托管路线。把字体文件下到自己的CDN、转成WOFF2、做了子集化,少了第三方那一跳,字体到场快了一大截。

品牌站那个标题,最后怎么做到秒显不跳?

回到那个空白三秒又抽动的标题。我们的组合拳是这样打的:字体从第三方托管改成自托管,转WOFF2、做子集化,文件从两百多KB压到几十KB;font-display设成swap,让标题第一时间用后备字体显示、不再隐形;再给后备字体配上size-adjust和度量覆盖,让它和品牌字体占一样的空间;关键字体加preload早早开始下载。

改完的效果,用设计师的话说是脱胎换骨:标题进页面立刻可读,不再有那段廉价的空白;品牌字体换入时,因为度量对齐了,几乎看不出跳动,CLS从0.12降到0.02。用户拿到的是一个既快又稳、还保住了品牌调性的首屏。客户后来算了笔账,这个改动上线后,移动端首屏的跳出率降了几个百分点,对一个靠首页承接投放流量的品牌站来说,省下的都是真金白银的广告费。

这事的启发是:字体优化不是二选一的取舍,不是只能在空白和跳动之间挑一个受。把瘦身、font-display、度量覆盖、preload这几招配齐,完全可以做到又快、又稳、又好看。别再让一个字体文件,毁了你精心设计的第一印象。

常见问题解答

font-display到底该设swap还是optional?

看你更怕什么。怕内容迟迟不显示、影响可读性和LCP,就用swap,让文字第一时间出来。怕字体换入引起布局跳动、拉高CLS,就用optional,它在字体没及时到时干脆不换、留到下次缓存命中再用,几乎不跳。如果你既想要swap的即时可读、又不想跳,那就配合度量覆盖去消跳动,鱼和熊掌可以兼得。

不设font-display会怎么样?

浏览器会走默认行为,大多数接近block,也就是字体加载期间文字隐形(FOIT),最长隐形约3秒。网速慢时,用户会盯着一片空白等字体。所以只要你用了自定义字体,就该显式设一个font-display,别把体验交给默认值。至少设个swap,保证文字第一时间可读。

preload字体是不是加了就一定好?

不是,preload要省着用。它是告诉浏览器最高优先级地拉这个资源,只该用在首屏真正关键的字体上,通常一两个就够。你要是把七八个字重全preload了,反而会挤占带宽、拖慢别的关键资源,得不偿失。preload的原则是精准打击首屏必需,不是撒网。

中文字体这么大,网页字体优化还有救吗?

有救,但要靠子集化。中文字库动辄几MB,全量加载确实不现实。可你单个页面用到的字其实有限,把用到的字符抽出来做成子集,体积能降到几十KB甚至更小。配合WOFF2和按需分包,中文网页字体完全能用得起。实在追求极致,也可以只给标题这类少量文字上自定义字体,正文用系统字体。

size-adjust这些度量覆盖,浏览器支持度够吗?

主流现代浏览器都支持了,可以放心用。对不支持的老浏览器,它会优雅降级——顶多是字体换入时该跳还是跳,不会导致页面出错。所以这是个纯赚不赔的渐进增强:支持的浏览器享受无跳动,不支持的也不受影响。值得给关键字体都配上。

字体加载慢,会直接影响SEO排名吗?

是间接影响。字体加载拖慢文字显示会影响LCP,引起换入跳动会影响CLS,这两个都是核心网页指标,属于排名参考信号。但更实在的影响是体验——标题空白、内容抽动,会让用户觉得站廉价、不专业,跳出率跟着涨。把字体治好,既是给指标加分,也是给品牌形象和转化率兜底,两头都划算。想知道字体加载在整套页面体验信号里排第几、值不值得优先投入,可以参考我写的 Page Experience六项体验信号怎么排序

权威参考资料

分享到
标签
版权声明

本文标题:《网页字体加载怎么优化?FOIT、FOUT和font-display的机制与实战》

本文链接:https://zhangwenbao.com/web-font-loading-font-display-foit-fout-optimization.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交