升级至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>
开发建议
不同的浏览器有不同的字体渲染引擎、方式。你基于一个浏览器计算得出的大小并不一定适用于另一个浏览器。所以我们尽可能不要指定文本容器的宽度,而让文本自适应于容器中,如果一定要指定宽度,那么尽量在文本周围留有一些空间避过于紧密的布局模式。