动态加载字体需插入唯一font-family的@font-face规则并清除旧规则,配合fontface.load()捕获错误,且woff2须配置cors,本地文件需http服务而非file://协议。

怎么用 @font-face 动态加载字体文件而不刷页面
核心是绕过浏览器默认的字体缓存机制,让每次换字体时都真实触发加载和渲染。直接改 document.body.style.fontFamily 不会重新解析 @font-face 规则,必须动态插入新规则。
- 先用
document.styleSheets[0].insertRule()插入带唯一font-family名的@font-face,比如font-family: "preview-woff2-123" - 再把预览区域的
style.fontFamily设为这个唯一名称,强制重绘 - 加载前清掉旧规则:遍历
document.styleSheets[0].cssRules,用deleteRule()删除所有含@font-face的项(注意 IE 需用removeRule()) - woff2 文件需配好 CORS 响应头(
Access-Control-Allow-Origin: *),否则 Chrome 会静默失败且不报错
为什么本地上传的 .ttf/.otf 在 Chrome 里显示异常
Chrome 对本地文件协议(file://)下加载的字体限制极严:即使用了 @font-face,只要路径是 file:///xxx.ttf,就会被拒绝解析,控制台只显示 Failed to decode downloaded font,实际根本没发请求。
- 必须起一个本地服务(如
npx serve或 Python 的python -m http.server),让页面走http://localhost - 上传后不要直接用
URL.createObjectURL(file)给src: url(...)—— 这在 Safari 下会失效,应读取为ArrayBuffer,再用new Blob([buffer], {type: 'font/ttf'})构造可跨浏览器的 URL - OTF 文件若含 CID 字体表,部分浏览器渲染会偏移,建议转成 TTF 再试
如何对比多字体在同一段文字下的行高、字间距、断行效果
单纯改 font-family 会导致行高继承、内边距浮动,无法真实反映排版差异。关键是要锁定所有影响视觉对齐的 CSS 属性。
- 给每个预览容器统一设置:
line-height: 1.4、letter-spacing: 0、word-break: keep-all、text-rendering: optimizeLegibility - 用
getComputedStyle(el).lineHeight拿真实像素值,别信 CSS 中写的1.4—— 不同字体的em单位实际高度可能差 2–3px - 对比时把文字内容固定为「中华人民共和国」+「The Quick Brown Fox」,覆盖中英文、标点、连字等典型 case
- 避免用
innerText测量宽度:它会忽略隐藏字符和空白符处理差异,改用el.getClientRects()[0].width取首行渲染宽度
字体加载失败时怎么给用户明确反馈
字体加载是异步且静默的,onerror 不会触发,FontFace.load() 是唯一可靠入口,但兼容性需兜底。
- 用
const font = new FontFace('test', 'url(xxx.woff2)')+font.load().catch(e => {...}),注意 Safari 15.4+ 才支持load(),老版本需 fallback 到定时检测document.fonts.check('12px "test"') - 失败后不要只写“加载失败”,要具体到:文件 404(检查
network面板)、CORS 被拒(看响应头)、格式不支持(如 iOS Safari 不认 woff2)、字体名含空格未加引号(src: url(x.woff2) format('woff2')缺引号会解析失败) - 预览区加一层半透明蒙层 +
pointer-events: none,上面浮一层小图标和文案,比弹 alert 更不打断操作流
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











