调整网页中的文字大小是前端开发里最基础却最容易踩坑的事。现代项目习惯用rem、vw这类相对单位实现响应式排版,但一旦需要支持旧版IE8、IE9或部分内置浏览器,这些新单位会被直接忽略,文字回退到默认大小,导致布局错乱。理解浏览器对不同单位的解析差异,才能写出既能兼容老环境又不牺牲新体验的样式。

一、HTML与CSS中控制文字大小的传统方式
在老浏览器环境里,最稳妥的文字大小控制手段仍然是像素单位px以及em、百分比。px是绝对参考值,浏览器会严格按照数值渲染,不会因为容器或根元素变化而缩放。比如给段落设置font-size: 14px;,在IE6到IE11中表现完全一致。这种确定性是老项目维护时最看重的特性。
em单位则相对于父元素的字体大小计算,适合做局部缩放。例如父级是16px,子级写font-size: 0.875em;就等于14px。百分比和em本质类似,只是书写形式不同。需要注意的是,em存在多层嵌套时计算复杂的问题,每一层都会乘以上级字号,稍不留神就会出现文字过大或过小。因此在老浏览器方案中,常用px定基准,em做模块内微调。
使用这些传统单位时,HTML结构也要配合。比如用<span>包裹需要特殊大小的文字,或在<body>上统一设基准px,再由内部标签用em延展。下面是一段兼容老浏览器的典型写法,把所有文字大小锚定在像素级,避免任何新单位参与计算。
body {
font-size: 14px;
}
.content {
font-size: 1em;
}
.sidebar {
font-size: 12px;
}
.note {
font-size: 0.857em; /* 相当于12px当父级是14px */
}
二、为什么老浏览器不认rem、vw等新单位
rem是CSS3引入的单位,意为相对于根元素<html>的字体大小。规范规定浏览器必须先读取根节点字号再换算,但IE8及更早版本根本没有实现这部分语法树解析,遇到font-size: 1.2rem;会当作非法声明直接丢弃,元素退回继承值。vw、vh依赖视口尺寸计算,同样在旧引擎中返回未知单位错误。
从渲染原理看,老浏览器内核采用固定单位映射表,只注册了px、pt、em、ex、百分比等少量标识符。新单位在词法分析阶段就被标记为无效令牌,不会进入级联计算。这也是为什么在旧项目里用新单位调文字大小,页面看起来像没写样式。开发者工具里甚至看不到这条规则被应用。
为验证这一点,可以用下面这段探测代码判断浏览器是否支持rem。思路是写一个隐藏元素,设rem值后读计算字号,若和预期px不符就说明不支持,从而走降级逻辑。
function supportRem() {
var el = document.createElement('div');
el.style.fontSize = '1rem';
el.style.position = 'absolute';
el.style.visibility = 'hidden';
document.body.appendChild(el);
var ok = window.getComputedStyle(el).fontSize !== '1rem';
document.body.removeChild(el);
return ok;
}
if (!supportRem()) {
document.documentElement.className += ' no-rem';
}
三、兼顾老浏览器与新浏览器的渐进增强方案
渐进增强的核心是先写老浏览器能用的px基准,再用媒体查询或能力类名为新浏览器追加rem规则。比如默认写font-size: 14px;,当根节点带rem-ok类时覆盖为font-size: 0.875rem;(假设根字号16px)。这样旧环境走px保底,新环境获得响应式弹性。这种双写方式增加了少量CSS,但彻底规避了破版风险。
另一种常见做法是使用JavaScript在加载时统一设置根字号,然后全部用rem。但老浏览器不认rem,js设了也无效,所以必须配合上面说的降级。也可以引入polyfill脚本,把rem声明在旧浏览器里手动换算成px写入行内样式。不过polyfill会增加请求与执行成本,在内部旧系统里往往不如直接双写来得直白。
下面给出一个完整的HTML片段示例,展示如何在不依赖新单位的情况下,用px与em完成文字大小调整,并通过简单脚本为现代浏览器开启rem增强。注意代码中的标签名在讨论时都已转义,实际书写为正常标签。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<style>
html { font-size: 16px; }
body { font-size: 14px; }
.box { font-size: 1em; }
.box .small { font-size: 0.857em; }
.rem-ok body { font-size: 0.875rem; }
.rem-ok .box .small { font-size: 0.75rem; }
</style>
</head>
<body>
<div class="box">
正文默认大小
<span class="small">辅助说明文字</span>
</div>
<script>
var t = document.createElement('div');
t.style.fontSize = '1rem';
document.body.appendChild(t);
if (window.getComputedStyle(t).fontSize !== '1rem') {
document.documentElement.className += ' rem-ok';
}
document.body.removeChild(t);
</script>
</body>
</html>
经过这样的处理,老浏览器用户看到的是精确像素排版,新浏览器用户则享有根字号变动带来的整体缩放能力。在维护历史项目时,与其强行统一新单位,不如用这种分层策略降低兼容成本,也方便后续逐步淘汰旧规则。