You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态注入含@font-face的样式表引发文本短暂不可见问题

解决动态注入含@font-face的外部样式表导致文本短暂不可见的问题

兄弟,你碰到的这个是典型的 FOIT(Flash Of Invisible Text) 问题,再加上动态加载外部样式表的特殊性,才会出现没法直接操作样式表规则的情况。我给你拆解几个实用的解决方案:

一、最省心的方案:给@font-face加上font-display: swap

FOIT的根源是浏览器默认会等自定义字体加载完才显示文本,而font-display: swap能告诉浏览器:先显示系统 fallback 字体,等自定义字体加载完成后再无缝替换,从根源上解决文本短暂不可见的问题。

如果你能控制外部样式表的内容,直接在每个@font-face规则里加这个属性就行:

@font-face {
  font-family: 'YourCustomFont';
  src: url('your-font.woff2') format('woff2');
  font-display: swap; /* 关键属性,解决FOIT */
}

要是没法修改外部样式表,接着往下看其他方法。

二、正确监听样式表加载,确保能访问它的规则

你说样式表没出现在document.styleSheets里,大概率是两个原因:要么是样式表还没加载完成,要么是跨域导致浏览器限制访问。

1. 等待样式表加载完成再操作

动态注入样式表时,一定要等它加载完成后再去遍历document.styleSheets。用link元素的onload事件来处理:

const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '你的外部样式表URL';

// 样式表加载完成后再处理规则
link.onload = function() {
  [...document.styleSheets].forEach(sheet => {
    try {
      // 匹配到刚加载的样式表
      if (sheet.href === link.href) {
        // 遍历所有规则,找到@font-face并修改
        [...sheet.cssRules].forEach(rule => {
          if (rule.type === CSSRule.FONT_FACE_RULE) {
            rule.style.fontDisplay = 'swap';
          }
        });
      }
    } catch (e) {
      console.log('这个样式表是跨域的,暂时没法访问cssRules');
    }
  });
};

document.head.appendChild(link);

2. 处理跨域样式表的访问限制

如果外部样式表是跨域的,浏览器会因为同源策略阻止你访问它的cssRules,这时候需要两步操作:

  • 让样式表所在服务器的响应头加上Access-Control-Allow-Origin,允许你的域名访问;
  • 同时在动态创建的link元素上添加crossorigin属性:
link.crossOrigin = 'anonymous'; // 如果需要携带凭证,就用'use-credentials'

这样处理后,就能正常访问跨域样式表的规则了。

三、绕过样式表访问:预加载字体+自定义@font-face规则

要是上面的方法都没法实现(比如没法改服务器配置,也没法修改外部样式表),可以换个思路:

  1. 先预加载字体文件,确保字体加载完成后再应用样式;
  2. 自己在页面中添加带有font-display: swap的@font-face规则,提前定义字体行为。

示例代码:

// 1. 预加载字体文件
const fontPreload = document.createElement('link');
fontPreload.rel = 'preload';
fontPreload.href = '你的字体文件URL';
fontPreload.as = 'font';
fontPreload.type = 'font/woff2';
fontPreload.crossOrigin = 'anonymous'; // 跨域字体一定要加这个

// 2. 字体预加载完成后,添加自定义@font-face规则
fontPreload.onload = function() {
  const style = document.createElement('style');
  style.textContent = `
    @font-face {
      font-family: 'YourCustomFont';
      src: url('你的字体文件URL') format('woff2');
      font-display: swap;
    }
  `;
  document.head.appendChild(style);
  
  // 最后注入外部样式表
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = '你的外部样式表URL';
  document.head.appendChild(link);
};

document.head.appendChild(fontPreload);

这样本地的@font-face规则会先生效,加上font-display: swap就不会出现文本不可见的情况了。


内容的提问来源于stack exchange,提问作者adam7918

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 08:52:33