浏览器默认字体大小并不是固定的16像素。虽然大多数桌面浏览器出厂设置是16px,但用户在设置中修改默认字号后,medium关键字对应的实际像素值会改变。例如Chrome允许在设置里调整字体大小,移动端浏览器也可能根据屏幕密度使用不同的默认值。JavaScript没有直接暴露读取浏览器默认字号的接口,不过可以借助CSS计算样式间接获取。本文将围绕medium关键字展开,介绍临时元素测量和iframe隔离测量两种方案,并说明实际应用中的兼容性问题。

理解CSS中的medium关键字与默认字号
在CSS规范中,font-size属性的初始值是medium。这个关键字并没有被规定必须等于16px,而是表示用户代理的默认字号,由浏览器或用户偏好决定。换句话说,如果用户把浏览器默认字体从16px改为18px,那么所有使用medium的元素都会跟随渲染为18px。正是这个特性,让我们可以通过测量medium元素来获取浏览器默认字体大小。
最简单的实现思路是在主文档中创建一个临时元素,把它的内联样式font-size设置为medium,然后追加到<body>里,再用getComputedStyle读取最终计算结果。为了让这个临时元素不干扰页面布局,可以把它定位到屏幕外并隐藏。完整代码如下:
function getDefaultFontSizeByMedium() {
const span = document.createElement('span');
span.style.fontSize = 'medium';
span.style.position = 'absolute';
span.style.left = '-9999px';
span.style.visibility = 'hidden';
document.body.appendChild(span);
const size = window.getComputedStyle(span).fontSize;
document.body.removeChild(span);
return parseFloat(size);
}
console.log(getDefaultFontSizeByMedium());
这个方法在大多数情况下是准确的,因为内联样式的优先级高于普通作者样式。但如果页面中存在类似* { font-size: 20px !important; }这样的全局规则,内联的medium也可能被压制,最终读取到错误的结果。另外某些浏览器提供最小字号设置,当用户设置的最小字号大于默认字号时,medium元素同样会被提升到最小字号,返回的值就不再是理论上的默认字体大小。这些问题在普通网页中并不常见,但如果你正在开发无障碍相关的功能,需要更稳定的测量环境。
用iframe隔离页面样式提高测量准确性
主文档中的样式污染主要来自作者样式表,尤其是带有!important的规则。为了彻底排除这些干扰,可以创建隐藏的<iframe>,因为同源iframe拥有独立的文档环境和样式计算,不会继承父页面的任何CSS。在iframe内部创建一个medium元素进行测量,就能得到浏览器真正基于默认设置计算出来的字号。
下面是使用iframe隔离的示例代码。先动态创建iframe并设置为不可见,通过srcdoc写入一个没有任何CSS的空白HTML文档,然后在其中创建段落元素并设置font-size: medium,最后读取计算结果并清理iframe。
function getDefaultFontSizeByIframe() {
const iframe = document.createElement('iframe');
iframe.setAttribute('aria-hidden', 'true');
iframe.style.width = '0';
iframe.style.height = '0';
iframe.style.border = 'none';
iframe.style.position = 'absolute';
iframe.style.left = '-9999px';
iframe.srcdoc = '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body></body></html>';
document.body.appendChild(iframe);
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const p = iframeDoc.createElement('p');
p.style.fontSize = 'medium';
iframeDoc.body.appendChild(p);
const size = parseFloat(iframeDoc.defaultView.getComputedStyle(p).fontSize);
document.body.removeChild(iframe);
return size;
}
console.log(getDefaultFontSizeByIframe());
这段代码的返回值和上一个方法在正常环境下通常相同,但在页面样式复杂时能给出更可靠的结果。iframe加载srcdoc后,如果不需要处理旧版IE,直接访问contentDocument一般没有问题。如果担心加载时序,可以监听load事件后再测量。频繁调用时,每测一次就创建一个iframe会产生一定性能开销,建议将隐藏iframe缓存起来复用,只在需要时重新测量。
实际应用与兼容性细节
获取到浏览器默认字体大小后,一个常见用途是调整rem基准。CSS中的rem单位相对于<html>元素的字号,而浏览器默认情况下html元素的字号与medium相同。如果页面没有显式设置html的font-size,那么1rem就等于浏览器默认字号。假设用户默认字号为20px,前端可以在根元素上按比例设置字号,让整个页面跟随用户偏好缩放。反过来,也可以计算一个缩放系数,例如const scale = defaultFontSize / 16;,用于需要以16px为设计基准的项目。
在解析getComputedStyle返回的fontSize时,结果始终是一个像素字符串,比如16px或18px。因此不必手动处理单位转换,使用parseFloat取出数字部分即可。需要注意的是,用户设置的最小字号可能让测量值大于默认字号。Chrome的最小字号默认是0,但用户可以手动调整。如果最小字号设置为17px而默认字号为16px,最终medium元素的字号会是17px。在无障碍场景下,这个限制往往符合用户的实际阅读需求,取测量值作为适配基准反而更合理。
兼容性方面,getComputedStyle在现代浏览器以及IE9及以上版本都可以使用。使用srcdoc的iframe方案在旧版IE中不受支持,需要改为设置src为about:blank,并在load事件回调中向iframe文档写入内容再测量。对于移动端浏览器,两种方案都能正常工作。最终可以选择一个健壮的封装:优先尝试iframe方法,异常时回退到临时元素方法,同时缓存结果以降低重复测量的开销。
总体而言,获取浏览器默认字体大小并不复杂,关键是理解medium关键字的作用以及页面样式可能带来的影响。对于普通项目,临时元素方法已经足够;如果页面包含大量全局样式或需要精确测量,建议使用iframe隔离方案。这样可以更稳定地根据用户偏好动态适配字体,提升可访问性。

