Web 字体加载与布局稳定:避免意外位移
了解 Web 字体如何影响布局稳定,选择可靠的加载策略,并在字体加载或失败时保持文字可读。
Web 字体可以改善品牌表现和阅读体验,但晚到的字体替换会在用户操作时移动文字、控件和图片。稳定布局需要把字体视为加载计划的一部分:先显示可用的回退字体,预留文字空间,并让最终字体的度量尽量接近回退字体。CSS Fonts 与 Font Loading 标准提供浏览器能力,却没有规定唯一策略。
CSS Fonts 规范说明字体描述符和 font-display 行为,CSS Font Loading API 提供在应用确实需要时协调字体状态的接口。MDN 的 font-display 参考记录浏览器行为和兼容性。它们支持稳定的展示决策,不支持字体枚举或设备识别。
字体为何会移动页面
文字空间取决于字形宽度、上升部、下降部、行距和字号。系统回退字体可能比目标字体宽或窄,替换后标题会换行,按钮会变宽,下方内容也会移动。即使视觉相似,度量也可能不同。网络延迟、缓存、连接策略和首屏使用位置都会改变冷加载与热缓存的结果。
把位移视为产品问题。关键不是字体最终是否到达,而是读者在等待期间能否理解和操作页面。保留可预测空间、保证控件可达,并让回退文字清晰可读。
依据任务选择 font-display
font-display 表达字体在阻塞、交换和失败阶段的偏好。swap 通常先显示回退文字,字体到达后再替换;optional 允许浏览器在等待成本过高时保留回退;fallback 只有短暂阻塞和有限交换期。具体时长由浏览器决定,文档不应承诺固定毫秒数。
正文应优先可读和稳定的段落宽度,装饰字体可以在回退仍清晰时使用 optional。图标字体不能是无障碍标签的唯一来源,必须提供文字或可访问 SVG。离线、请求被阻止或字体失败都应回到基础体验,而不是把缺失当成异常设备证据。
校准回退度量并预留空间
size-adjust、ascent-override、descent-override 和 line-gap-override 可让回退度量更接近目标字体,但不能保证每种文字和字重都一致。应使用各语言的标题、正文、数字和标签进行测量,并记录调整值。浏览器不支持描述符时,普通回退仍须可读。
布局应使用弹性网格、minmax()、自动换行和内容高度,避免绝对定位承载会改变行数的文字。按钮应能换行并保持焦点可见,最长本地化标签也要测试。不要列出大量本地已安装字体来探测环境;选择小而稳定的字体栈即可。
只加载当前页面需要的字体
声明路由实际使用的字重和样式,删除未使用子集。unicode-range 可用于大型文字系统,但混合脚本要测试二次回退和二次位移。只有首屏关键且可可靠缓存的字体才适合预加载,不能让字体抢占 HTML、CSS 或重要图片的带宽。
Font Loading API 可在测量组件、导出文档或启动画布任务前等待指定字体。不要因普通正文而阻塞页面;只在确有任务依赖时等待,并合并重复布局更新。特性检测接口,捕获拒绝 Promise,在 document.fonts 不存在或请求被阻止时保留回退路径。
保持无障碍和多语言稳定
等待期间也要保持对比度、文字缩放、行距和焦点可见。不要向屏幕阅读器播报每次字体替换,只有在字体缺失导致导出不可用等真实影响时才提供状态。尊重放大文字、强制颜色和减少动态效果偏好,字体替换不应移除焦点环。
测试空缓存、热缓存、延迟、离线、阻止请求及不支持 Font Loading API 的浏览器。检查首屏文字、最终换行、焦点顺序和主要操作。每种语言都使用最长标题和标签,确认缺失子集不会折叠按钮或遮住错误信息。测试配置可以记录浏览器、视口和网络条件,但不要上传字体清单或详细计时历史。
隐私、缓存与发布复查
字体是否加载是当前页面的运行事实,不应变成账户属性、字体清单或设备分类。遥测记录 font_policy=fallback 等决策结果即可,不要保存原始字体列表、响应时间或字符级测量。若故障排查暂时需要更多细节,应限制访问并在事件结束后删除。
使用内容寻址 URL 和与发布流程匹配的缓存策略。字体版本更新时复查导航、表单、表格、价格、日期和错误信息;若出现位移,可独立回滚字体或度量描述符。离线和中断更新也要保留系统字体路径。
字体加载属于性能预算。
回退字体保持正文可见。
标题换行应自然发生。
按钮标签必须完整显示。
长数字也需要测试。
省略装饰不会影响任务。
网络延迟不是用户错误。
缓存命中不代表永远稳定。
字体失败应回到系统字体。
离线页面仍应可读。
字体策略属于展示层。
权限逻辑不能依赖字体。
服务端无需字体清单。
日志只保留策略结果。
及时删除临时调试字段。
不要建立字体画像。
明确解释等待状态。
保持键盘焦点可见。
触摸目标不能被挤走。
文字放大后仍要换行。
强制颜色模式需要复查。
阅读顺序不能随替换改变。
对话框位置应重新计算。
表格可以提供滚动区域。
虚拟列表应保留缓冲。
导出任务可以提供替代格式。
测试应使用合成内容。
测试记录浏览器配置。
不记录安装字体集合。
多语言共享同一限制。
翻译不能改变情态。
可选能力不能写成保证。
版本更新需复查度量。
样式表与字体应一致发布。
失败请求不应循环重试。
预加载必须有明确理由。
子集边界需要混合脚本测试。
图标必须有文字名称。
备用路径应可逆。
用户偏好应明确选择。
页面刷新不应丢失输入。
最终目标是稳定阅读。