解决使用 Web 字体的过渡问题

博客使用霞鹜文楷 web 字体已经有一段时间,体验下来这款字体还是非常不错的。但一直存在一个问题,就是由于浏览器在解析 CSS 和加载 web 字体之间存在延迟,浏览器会首先直接显示默认字体样式,随后才能逐渐切换为加载完毕的 Web 字体。这段时间能够非常明显的看到整个字体的变化过程,甚至会产生界面跳动现象,感觉非常不爽。

最近无意间找到了一个折衷的解决办法,可以在页面加载和字体加载完成之前隐藏整个页面内容,并在字体加载完成后通过动画平滑显示页面。虽然这个方法会影响页面前期的显示速度,但是经过测试感觉对速度的影响并不是很大。如果能够隐藏整个字体的变化过程,显示效果会舒服很多。因此,牺牲一些前期页面的显示速度还是可以接受的。

下面是具体实现代码及其解释:

样式代码:

<style> /* 设置 HTML 元素默认不可见 */ html { visibility: hidden; /* 隐藏页面内容 */ opacity: 0; /* 将透明度设置为 0 */ transition: opacity 0.2s ease; /* 定义透明度的过渡效果,持续 0.2 秒 */ } /* 当 HTML 元素具有 'ready' 类时 */ html.ready { visibility: visible; /* 页面可见 */ opacity: 1; /* 将透明度恢复为 1,显示页面内容 */ } </style>

功能说明:

• 初始设置 html 元素的 visibility 为 hidden 和 opacity 为 0,让页面在加载阶段保持隐藏状态。

• 使用 CSS 的 transition 属性,在页面内容显示时添加过渡效果。

• 当字体加载完成或超时时,通过 JavaScript 给 html 元素添加 ready 类,恢复 visibility 和 opacity。

脚本代码:

<script> // 确保在页面加载时移除 'ready' 类,以便隐藏页面内容 document.documentElement.classList.remove('ready'); // 定义一个函数,用于显示页面 function showPage() { // 为 HTML 元素添加 'ready' 类,使页面内容显示 document.documentElement.classList.add('ready'); } // 检查浏览器是否支持 document.fonts 接口 if (document.fonts) { // 如果支持,等待页面字体加载完成后执行 showPage 函数 document.fonts.ready.then(showPage); // 如果字体加载超时(3 秒内未完成),强制显示页面 setTimeout(showPage, 3000); } else { // 如果浏览器不支持 document.fonts,则在 500 毫秒后强制显示页面 setTimeout(showPage, 500); } </script>

功能说明:

1. 字体加载检测:

• 使用 document.fonts.ready API 检测字体加载完成后调用 showPage()。

• 如果浏览器不支持 document.fonts,使用定时器(setTimeout)在 500 毫秒后显示页面。

2. 超时机制:

• 在字体加载等待超时(如 3 秒)后,强制调用 showPage(),避免长时间页面不可见的问题。

使用方法:将上述样式代码和脚本代码添加到 head 标签内即可。


上述确实存在闪动问题,而且在排查该问题的过程中,又发现了一个由于自己前期改动而引发的新问题…代码如果能正常运行,还真是不要轻举妄动,果然牵一发而动全身!这么一个小问题竟然绕了好多弯路,现将调整后的代码记录如下:

<style> html { opacity: 0; } html.ready { opacity: 1; } </style> <script> function showPage() { document.documentElement.classList.add('ready'); } if (document.fonts) { document.fonts.ready.then(showPage); setTimeout(showPage, 3000); } else { setTimeout(showPage, 500); } </script>