如何借助Font Access API异步获取用户系统的原始字体列表并渲染到DOM

作者:袖梨 2026-06-07
Font Access API(queryLocalFonts)是Chromium 125+支持的安全异步接口,用于获取用户本地字体元数据,需显式授权,返回family、fullName等字段,不提供字体文件,须降级兼容并注意隐私与渲染安全。

Font Access API(即 queryLocalFonts())是现代浏览器中用于安全、异步访问用户本地已安装字体的标准化接口。它不返回字体文件本身,而是提供每个字体的元数据(如 family、fullName、postscriptName、style、weight、stretch 等),且需用户明确授权(首次调用会触发权限提示)。该 API 目前仅在 Chromium 125+(Chrome/Edge 125+、Opera 111+)中稳定支持,Firefox 和 Safari 尚未实现。

检查支持性与请求权限

使用前必须检测 API 可用性,并理解其权限模型:调用 navigator.fonts.queryLocalFonts() 会触发一次性的用户授权弹窗(类似摄像头或地理位置),后续调用将静默返回结果。

  • 先判断 'fonts' in navigator && 'queryLocalFonts' in navigator.fonts
  • 权限状态可通过 navigator.permissions.query({ name: 'local-fonts' }) 获取,但实际调用 queryLocalFonts() 才真正触发授权流程
  • 不建议在页面加载初期自动调用——应由用户显式操作(如点击“加载本地字体”按钮)触发,避免干扰体验

异步获取并解析字体元数据

API 返回的是 FontMetadata 对象数组,每个对象包含结构化字段,而非原始二进制数据。你无法直接读取 .ttf 文件内容,但可可靠获取字体名称体系:

  • family:CSS 中使用的 font-family 名(如 "Inter", "微软雅黑")
  • fullName:完整显示名(如 "Inter Bold", "Microsoft YaHei UI Bold")
  • postscriptName:PostScript 标识符(常用于设计软件,如 "Inter-Bold")
  • styleweightstretch:可用于筛选或分组(例如只取 weight ≥ 600 的粗体)

示例代码:

async function loadLocalFonts() {<br>  try {<br>    const fonts = await navigator.fonts.queryLocalFonts();<br>    console.log(`共发现 ${fonts.length} 款本地字体`);<br>    return fonts.map(f => ({<br>      family: f.family,<br>      fullName: f.fullName,<br>      postscriptName: f.postscriptName,<br>      weight: f.weight,<br>      style: f.style<br>    }));<br>  } catch (err) {<br>    console.warn("获取本地字体失败:", err.message);<br>    return [];<br>  }<br>}

安全渲染到 DOM(避免样式污染与布局抖动)

获取字体列表后,**不能直接将其作为 font-family 值应用到全局样式**,否则可能引发不可控的回退行为或 FOIT/FOUT。推荐做法是:为每个字体创建隔离的预览容器,并使用 @font-face + font-display: optional 配合 FontFace API 按需加载(仅当用户选中某款字体时)。

  • 在 DOM 中为每款字体生成一个 <div class="font-preview">,内含测试文字(如 "AaBbYyZz 012345")
  • 设置 style="font-family: 'xxx', sans-serif;",利用系统已有字体直接渲染(无需下载)
  • 若需确保显示效果一致(比如跨设备预览),可对选中的字体调用 new FontFace(family, `url(${fallbackUrl})`) 加载网络后备,但注意:Font Access API 本身不提供字体文件 URL
  • 务必限制预览数量(如最多展示 100 条),避免长列表导致内存或渲染压力

注意事项与兼容性兜底

当前阶段该 API 属于渐进增强特性,生产环境必须提供降级方案:

  • 不支持时,可回退到内置字体列表(如 CSS 标准字体族、常见中英文字体名枚举)
  • 避免依赖 postscriptNamefullName 做关键逻辑——它们在不同系统上格式差异大(Windows/macOS/Linux 返回值风格不同)
  • 不要假设所有字体都支持中文;可用 document.fonts.check('12px "xxx"') 简单验证是否能渲染基础字符
  • 隐私敏感场景下,部分企业策略或浏览器扩展可能屏蔽该 API,需捕获 SecurityError 异常

相关文章

精彩推荐