升级至 IE11 后网页布局破坏最常见的原因是:IE11 使用了较新的文档模式来渲染页面。但有时候会发现一个页面即使使用了相同的文档模式,IE11 中显示的布局仍然被破坏了,这可能是由于 IE11 使用了一种全新的字体渲染模式:natural metrics
,在 IE11 之前 IE 都是使用传统的gdi metrics
。
问题表现
下面这段网页代码是在 IE7、8 年代开发的。开发者为了将一段文字显示在一行内指定了 DIV 容器的宽度。为了保证新版本 IE 浏览器能兼容该页面,开发人员还特地使用X-UA-Compatible
meta 标签来指定使用 IE7 文档模式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<style>
#top-box {
background: #ccc;
padding: 5px;
width: 330px;
}
</style>
</head>
<body>
<div id="top-box">
Single line text appears in a fixed width DIV container.
</div>
</body>
</html>
该页面在 IE8 到 IE10 中都显示正常:
然而升级至 IE11 后,文字变成了 2 行:
问题原因
默认情况下,IE11 使用了一种叫做natural metrics
的字体渲染引擎。Natural metrics
使用了像素间距来提供更加适宜阅读的文字渲染效果。之前 IE 浏览器使用的字体渲染为传统的GDI metrics
。从下图我们可以看出natural metrics
渲染的字体更加顺滑,不像GDI metrics
锯齿感那么明显。
由于之前开发是基于老版本的 IE 浏览器,330px 的宽度是基于GDI metrics
计算出来的。很显然,在 natrual metrics
中,330px 的宽度已经不足以将这段文字显示在一行内了。
相较于GDI metrics
,natural metrics
显示的每一个文字会更宽一些。我们可以通过下面的代码来测量文字:“ABC”在两种模式下的宽度。
<span id="span">ABC</span>
<br />
<button id="show-offset" onclick="showoffset()">Show offset</button>
<script>
function showoffset() {
alert(document.getElementById('span').offsetWidth);
}
</script>
在 IE8 到 IE10 中(GDI metrics
),“ABC”的宽度为 32。
在 IE11 中(natural metrics
),“ABC”的宽度为 33。
解决方案
客户端方案
把网站加入本地 Intranet 站点。IE11 对于本地 Intranet 的站点依然使用GDI metrics
来渲染字体。
代码方案
加入<meta http-equiv="X-UA-TextLayoutMetrics" content="gdi" />
meta 标签以强制浏览器使用GDI metrics
来渲染文字。
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<meta http-equiv="X-UA-TextLayoutMetrics" content="gdi" />
<style>
#top-box {
background: #ccc;
padding: 5px;
width: 330px;
}
</style>
</head>
<body>
<div id="top-box">
Single line text appears in a fixed width DIV container.
</div>
</body>
</html>
开发建议
不同的浏览器有不同的字体渲染引擎、方式。你基于一个浏览器计算得出的大小并不一定适用于另一个浏览器。所以我们尽可能不要指定文本容器的宽度,而让文本自适应于容器中,如果一定要指定宽度,那么尽量在文本周围留有一些空间避过于紧密的布局模式。