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

更换fontFamily后元素clientWidth获取值不准确问题咨询

问题原因

你遇到的宽度不匹配问题核心是自定义字体加载时序和DOM渲染时序不一致:
你引入字体时设置了display=swap,该配置会让浏览器优先使用系统 fallback 字体渲染文本,等Poppins字体加载完成后再替换重绘文本。mounted钩子仅代表Vue组件的DOM挂载完成,此时自定义字体大概率还未完成加载/替换,你拿到的是 fallback 字体渲染的宽度,等字体替换完成后元素实际宽度发生变化,就出现了数值不匹配的情况。即使是本地字体也存在文件加载、解析的时间差,不会在DOM挂载瞬间就完成渲染。

注意:你提供的字体引入代码存在语法错误,rel="stylesheet缺少闭合双引号,修复后才能保证字体正常加载:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">

解决方案

方案1:使用Font Loading API监听字体加载完成后再获取宽度(最推荐)

浏览器原生提供的Font Loading API可以精准监听字体加载完成的时机,直接在回调中获取宽度即可保证数值准确:

<template>
  <div id="poppins" style="display: inline-block;">Item One a</div>
</template>

<script>
export default {
  name: 'App',
  async mounted () {
    // 等待所有字体加载完成
    await document.fonts.ready
    // 也可以指定监听特定字体加载完成,例如:
    // await document.fonts.load('16px Poppins')
    console.log(document.getElementById('poppins').clientWidth)
  }
}
</script>

方案2:调整font-display配置

如果你可以接受短暂的文本不可见,可以将字体引入中的display=swap改为display:block:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display:block">

该配置下,字体未加载完成时文本会隐藏,等字体加载完成后才会渲染,此时mounted阶段如果字体已经加载完成,拿到的宽度就是准确的。该方案缺点是网络差时会出现较长时间的文本空白。

方案3:全局控制内容渲染时机

如果需要保证全站所有自定义字体渲染完成后才展示内容,可以配合CSS实现:
首先在全局CSS中添加:

body {
  opacity: 0;
  transition: opacity .2s;
}
body.font-loaded {
  opacity: 1;
}

然后在入口文件监听字体加载完成后添加类名:

document.fonts.ready.then(() => {
  document.body.classList.add('font-loaded')
})

该方案下所有内容都会等字体加载完成后才展示,不存在字体切换的闪烁,此时任意阶段获取元素宽度都是准确的,缺点是首屏会有短暂的白屏时间。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:27:04