前言在完全加载之前和之后的一些布局变化很容易解决:为动态元素预分配正确的空间,在图像上使用宽度和高度属性,并优先考虑HTMLA可见文档中的元素。但是,还有另一个棘手的问题导致布局发生变化:无样式文本(FOUT)的闪烁。在这篇文章中,我们将探索令人惊讶的复杂文本渲染世界,以及一些处理无样式文本闪烁的技术。为什么字体会导致布局变化?意外的布局更改(页面内容在没有用户交互的情况下移动)对用户体验不利。下载网页字体时,当字体标题发生变化时,会导致包含元素(例如
、段落或段落)的大小发生变化,从而导致布局发生变化。当网络字体的字体高度或段落长度与系统字体不同时,就会发生这种情况。布局页面时,浏览器将使用后备字体的尺寸和属性来确定包含元素的大小,即使您已使用font-display:block!声明Web字体以阻止系统字体!“两种不同的字体可能会导致布局发生变化,但也不一定,主要看字体的字高。”如何避免我们现在的网页往往会使用一些特殊的字体来满足用户的审美,但同时也会带来一些体验问题,最常见的就是页面加载速度和文字闪烁。所以我们有必要对字体进行优化,以满足我们“越来越挑剔”的用户。font-display最粗暴的解决方案,一行CSS代码就可以解决。字体显示:可选;如果在呈现文本时网络字体不可用(加上100毫秒),为什么这一行代码足以告诉浏览器使用后备系统字体。这意味着在未缓存的页面加载中,可以使用后备字体,但所有后续页面加载都应使用网络字体呈现,因为它将被下载并在缓存中可用。它共有以下属性:"auto:"字体显示策略由用户代理设置"block:"为字体提供短阻塞期和无限交换期,等待时隐藏文本最多三秒web字体,总是在加载时交换web字体“swap:”给字体一个非常小的阻塞期和无限交换期,尽快显示文本,并且总是在加载时交换web字体“fallback:”给字体一个非常小的阻塞周期和短交换周期,隐藏文本长达100毫秒,然后仅在三秒内交换加载的网络字体“可选:”提供具有非常小的阻塞周期的字体,没有交换周期,隐藏文本长达100毫秒,thenonlyUseavailablewebfonts,neverswap如果上面的解释不清楚,可以看下图:“Optional是唯一保证没有布局偏移的字体显示值。”不幸的是,系统字体不一定是最好的设计,而且它们在操作系统之间也不一致。大多数设计人员一想到向用户展示另一种系统字体就会感到畏缩。接下来描述了各种优化,以更快地将字体文件传送到浏览器,允许使用任何字体显示选项,而显示系统字体的风险最小,或者用于可选以外的选项:不触发布局转换。优化字体文件优化网络字体有两种主要方法:子集化和格式化。子集字体许多字体会有多个字母的字形(一个字形是单个字符,例如a或&)如果您只提供拉丁字母(a-Z)并且不使用连字(例如é),那么这些字形表示字体文件中的浪费字节。从此字体中删除非拉丁字符会生成一个大小为六分之一的woff2文件。字体格式主流设备基本都支持woff2字体格式,所以没有必要在网站中引入多种不同格式的字体。一般建议只导入woff2,可以保持代码简洁,减少上传到服务器的文件。加载更少的字体虽然我们会将字体转换为woff2格式,但是文件大小仍然是几百K,有时甚至是几M,而且字体文件的大小也会影响页面的整体渲染速度。有时我们只需要特殊字体的几个字符,所以我们不需要导入整个字体文件。提取字体当我们遇到上述情况时,一定不要导入整个字体包,这样会极大地浪费网络带宽,影响页面加载。推荐使用font-spider提取文本。安装font-spidernpminstallfont-spider-g解压我们以上面的诗句为例,这里我们使用的是汉仪FlagBlack.woff2字体文件。这里压缩文库后大约是32K。让我们在项目目录中执行以下命令font-spiderindex.html。这时候会生成一个.font-spider目录,解压出来的字体文件就放在这个目录下。现在的字体文件只有10K左右,比以前小了好几倍。使用系统字体Web字体很受欢迎,因为它们允许设计人员在浏览器中保持一致的外观和感觉。如果不需要,系统字体将是呈现文本的最快方式。如果您当前的网络字体接近系统字体,您可以使用Monica的字体样式匹配器来调整字体设置,直到获得近乎完美的匹配。使用系统字体意味着文本将尽早呈现。我们现在还有一种方法可以将字体与操作系统相匹配,这可能比以前的替代方案(如Arial和Helvetica)更具吸引力。为此,我们需要按特定顺序列出所有操作系统的系统字体:body{font-family:-apple-system,BlinkMacSystemFont,"SegoeUI","Roboto","Oxygen","Ubuntu","Cantarell","FiraSans","DroidSans","HelveticaNeue",sans-serif;}字体文件的快速交付显然,为了确保字体在我们的网页上快速正确地应用,我们必须让浏览器下载我们的,在我们自己的CDN上托管字体将为您提供最佳性能。使用CDN托管通常,我们应该从我们的服务器提供字体,以避免连接到第三方服务器的成本,这对于高延迟连接尤为重要。使用第三方服务意味着您的字体将会延迟。最好的情况是您直接从另一个主机名(例如fonts.gstatic.com)请求字体文件,这会产生连接成本-DNS查找、TCP连接和TLS协商。最坏的情况是多跳,例如从引用fonts.gstatic.com上的文件的fonts.googleapis.com加载CSS文件,将导致两次连接丢失。因此,我们通常会在自己的CDN服务器上托管一些字体文件等静态资源,以加快资源的下载速度。缓存字体字体可以缓存在两个地方:“客户端和CDN”。客户端缓存对于会话中的导航很重要,应该以避免重新验证请求的方式进行。重新验证请求(if-not-modified和if-modified-since)将阻止浏览器使用字体文件,直到它验证它在服务器上没有更改。字体很少改变,所以我们应该实现一个缓存头如下,当字体改变时更新文件名以打破缓存:cache-control:max-age=31536000,immutable这告诉浏览器他们可以保持字体长达一年并且不需要重新验证(Firefox和Safari不可变支持,Chrome应该自动避免重新验证请求)。避免将ETag添加到这些响应中,因为它们可能会强制重新进行身份验证。还要检查您的内容交付网络配置是否可以将字体文件存储在缓存中,旧配置可能不包含.woff2扩展名,从而导致原始点击并降低响应速度。使用预加载一般来说,浏览器不会随便下载字体文件,它们会等到渲染树建好后才知道需要哪些字体。这意味着仅当浏览器在呈现文本之前下载并解析HTML和CSS时才会请求Web字体。“但重要的是要注意内联CSS不需要网络请求,这意味着我们的字体可以在页面加载的早期获取。”渲染树构建过程会阻止对Web字体的请求。但是如果我们确定在页面文字的渲染中会用到一些网页字体,我们可以使用preload让浏览器提前下载好字体文件。浏览器解析这行HTML后,立即发送对字体文件的高优先级请求。“不过需要注意的是,预加载请求会占用其他请求的带宽,所以我们需要在使用过程中考虑是否值得。”将字体转换为Base64的另一种常用方法是将字体用作嵌入在CSS中的Base64字符串,从而无需额外的字体请求并确保在呈现文本时字体可用。但是这种方法并不是绝对好的方法,它只适用于一些小的字体文件,比如上面提到的使用font-spider提取的字体文件,而且字体文件足够小,因为将字体文件转成Base64字符串往往会变大。一般来说,它有以下缺点:字体文件是压缩的二进制对象,将它们编码为Base64字符串会显着增加大小。CSS包的gzip或brotli压缩并不能完全弥补这种膨胀。字体会被发送到每个浏览器,即使有些浏览器不工作renderingReducelayoutoffsetswithf-modsF-mods是对字体描述符规范的建议更新,其中包括四个新描述符:“ascent-override(%)”:覆盖分配给ascenters“descent-override(%)”:overrideassignedtothedescender"line-gap-override(%)":overridethelinespacing"advance-override(#)":setanextraadvanceforeachcharacter,tohelpmatchlinewidthsandpreventwordsof字溢出。前三个都会影响线的高度:线框高度=上升+下降+线间距。基线位置=线框顶部+线间隙/2+上升。这四个描述符的组合允许我们通过告诉浏览器在下载网络字体之前字符将占用多少空间来覆盖后备字体的布局以匹配网络字体。f-mods只真正修改垂直间距和定位。这意味着字符间距和字母间距仍然需要处理,否则你可能会在不同的点处出现换行词,导致元素高度发生变化,从而导致布局发生变化。但是@font-face声明中没有letter-spacing和word-spacing属性,所以我们必须在body或element上声明它。@font-face{字体系列:自定义字体;src:url("./public/fonts/汉仪旗黑.woff2");}@font-face{font-family:fallback-font;来源:本地(宋体);上升覆盖:100%;下降覆盖:20%;线间隙覆盖:正常;advance-override:10;}/*这些具体值取决于字体,需要根据自己的字体计算调整*/body{font-family:custom-font,fallback-font;}.content{letter-间距:-1.1px;word-spacing:-0.2px;}总结简而言之,如果浏览器没有及时获取网页字体,可以将font-display:optional应用于网页字体,让浏览器以回退系统字体呈现,以防止布局漂移,否则我们只能优化我们的字体以尝试在浏览器需要它们之前将它们发送到浏览器:使用woff2最小化文件大小优化字体文件加载更少的字体预加载关键字体在CDN上托管字体文件使用f-mods减少字体交换的影响