打印

BX9007: 获取文档可视尺寸(视口)时在各浏览器中的参考元素有差异

作者:陆远 孙东国

标准参考

无。

问题描述

不同浏览器对文档实际视口元素的实际参照不同。

造成的影响

仅用单一方法获取文档元素的实际高度可能会与视口高度产生混淆。

受影响的浏览器

所有浏览器  

问题分析

'scrollHeight' 属性最初有微软在 IE4.0 中引入到其 'DHTML Object Model' 中,根据 MSDN 的描述,'scrollHeight' 是一个只读属性,返回对象内容上边界至下边界之间的垂直高度,即一个元素的实际滚动视野的高度。
在 MDC 中有如下描述,一个元素的 'scrollHeight' 是元素的内容(包括根据 'overflow' 特性决定的不可见部分)的高度。若一个元素的内容生成了垂直滚动条,'scrollHeight' 的值等于该元素所需 'clientHeight' 的最小值,以适应不使用垂直滚动条时视点中的所有内容。若一个元素的内容没有生成垂直滚动条,'scrollHeight' 的值等于其 'clientHeight' 的值。

1. 生成了页面垂直滚动条

在页面出现滚动条时,无论哪种文档模式,均可以通过 'document.body.scrollHeight' 获取到页面滚动条的实际高度。

分析以下代码 :

<!--iframe.htm--> <style> iframe { width:400px; height:80px; margin:0; padding:0; border:0;
                } </style> <table> <tr> <td> <iframe src="subQ.htm"
                frameborder="0"></iframe> </td> <td> <iframe src="subS.htm"
                frameborder="0"></iframe> </td> </tr>
                </table>
<!DOCTYPE html> <!--subS.htm--> <html> <head>
                <style> * { margin:0; padding:0; } #d { background:#DDD; height:100px; } </style>
                </head> <body> <div id="d"></div> <script>
                document.getElementById("d").innerHTML = 'document.documentElement.clientHeight:' +
                document.documentElement.clientHeight+ '<br />document.body.clientHeight:' +
                document.body.clientHeight + '<br />document.documentElement.scrollHeight:' +
                document.documentElement.scrollHeight + '<br />document.body.scrollHeight:' +
                document.body.scrollHeight; </script> </body> </html>
<!--subQ.htm-->
                <html> <head> <style> * { margin:0; padding:0; } #d { background:#DDD; height:100px; }
                </style> </head> <body> <div id="d"></div> <script>
                document.getElementById("d").innerHTML = 'document.documentElement.clientHeight:' +
                document.documentElement.clientHeight+ '<br />document.body.clientHeight:' +
                document.body.clientHeight + '<br />document.documentElement.scrollHeight:' +
                document.documentElement.scrollHeight + '<br />document.body.scrollHeight:' +
                document.body.scrollHeight; </script> </body> </html>

上面代码主页面 "iframe.htm" 中包含两个高度为 80px 的子页面 "subQ.htm" 与 "subS.htm" ,即子页面内视口内容的高度大于其窗口容器的高度,子页面的区别仅为文档模式不同,子页面内清除了所有元素的默认 padding 与 margin ,BODY 中有一个灰色背景的 DIV 元素,高度为 100px ,页面运行时在 DIV[id="d"] 中显示出下面 4 个返回值:

  • document.documentElement.clientHeight,HTML 元素的客户区域高度;
  • document.body.clientHeight,BODY 元素的客户区域高度;
  • document.documentElement.scrollHeight,HTML 元素的滚动区域高度;
  • document.body.scrollHeight,BODY 元素的滚动区域高度。

在各浏览器中效果如下:

IE6(Q) IE7(Q) IE8(Q) IE6(S) Opera(S) IE7(S) IE8(S) Firefox(S) Chrome(S) Safari(S) Firefox(Q) Chrome(Q) Safari(Q) Opera(Q)
document.documentElement.clientHeight 0 64 80 100
document.body.clientHeight 80 100 100 80
document.documentElement.scrollHeight 80 100 100 100
document.body.scrollHeight 100 100 100 100

可见,在生成页面垂直滚动条时,documnt.body.scrollHeight 的返回值均为 100px,差异出现在其他三个属性的返回值上:

  • IE6(Q) IE7(Q) IE8(Q) 中,HTML 文档的根元素为 BODY(参见:http://msdn.microsoft.com/en-us/library/bb250395%28VS.85%29.aspx#cssenhancements_topic4)。所以 document.document.clientHeight 返回值为0,document.body.clientHeight 为 IFRAME 对子页面限制的视口高度 80px。document.documentElement.scrollHeight 的值则不具备意义;
  • IE6(S) 中,浏览器同时为 IFRAME 内的子页面生成了水平滚动条,在测试的操作系统中横向滚动条高度为 16px,则 document.documentElement.clientHeight 的值为 80px 减去生成的水平滚动条的高度 16px,为 64px,其他三个值均为 100px;
  • Opera(S) 中,虽然没有生成 IE6(S) 中的水平滚动条,但只要 IFRAME 元素的 scrolling 属性不为 "no" ,浏览器在计算 document.documentElement.clientHeight 的值时就会减去可能生成的水平滚动条高度;
  • IE7 IE8 Firefox Chrome Safari(S) 中,与 Opera(S) 的区别就是 document.documentElement.clientHeight 的值没有减去水平滚动条的高度,为 80px;
  • Firefox Chrome Safari Opera(Q) 中,clientHeight 的两个值互换。

看以看出,在页面出现滚动条时,无论哪种文档模式,均可以通过 'document.body.scrollHeight' 获取到页面滚动条的实际高度。

其中特例为:由于 IE 混杂模式下的根元素为 BODY,这里对 BODY 元素设置宽度与高度无效,所以若 BODY 子元素的高度不足以生成页面滚动条时,'document.body.scrollHeight' 获取到的值会和其他浏览器有差异。

2. 没有生成页面垂直滚动条

分析以下代码:

<!--iframe.htm--> <style> iframe { width:400px; height:880px; margin:0; padding:0;
                border:0; } </style> <table> <tr> <td> <iframe src="subQ.htm"
                frameborder="0"></iframe> </td> <td> <iframe src="subS.htm"
                frameborder="0"></iframe> </td> </tr>
                </table>
<!--subS.htm--> <!DOCTYPE html> <html> <head>
                <style> * { margin:0; padding:0; } #d { background:#DDD; height:100px; } </style>
                </head> <body> <div id="d"></div> <script>
                document.getElementById("d").innerHTML = 'document.documentElement.clientHeight:' +
                document.documentElement.clientHeight+ '<br />document.body.clientHeight:' +
                document.body.clientHeight + '<br />document.documentElement.scrollHeight:' +
                document.documentElement.scrollHeight + '<br />document.body.scrollHeight:' +
                document.body.scrollHeight; </script> </body> </html>
<!--subQ.htm-->
                <html> <head> <style> * { margin:0; padding:0; } #d { background:#DDD; height:100px; }
                </style> </head> <body> <div id="d"></div> <script>
                document.getElementById("d").innerHTML = 'document.documentElement.clientHeight:' +
                document.documentElement.clientHeight+ '<br />document.body.clientHeight:' +
                document.body.clientHeight + '<br />document.documentElement.scrollHeight:' +
                document.documentElement.scrollHeight + '<br />document.body.scrollHeight:' +
                document.body.scrollHeight; </script> </body> </html>

上面代码与上一节中的测试代码类似,区别仅为主页面 "iframe.htm" 中 IFRAME 元素的高度变为 "880px",即子页面视口内容的高度小于其窗口容器的高度。

在各浏览器中效果如下:

IE6(Q) IE7(Q) IE8(Q) IE6(S) IE7(S) IE8(S) Firefox(S) Firefox(Q) Opera(Q) Opera(S) Chrome(Q) Safari(Q) Chrome(S) Safari(S)
document.documentElement.clientHeight 0 880 880 100 100 864 880 880
document.body.clientHeight 880 100 100 880 864 100 880 100
document.documentElement.scrollHeight 880 100 880 100 100 100 880 100
document.body.scrollHeight 100 100 100 880 864 100 880 880

本例中,IFRAME 元素内的子页面并没有生成垂直滚动条,此时的 scrollHeight 的值已不具备其实际意义。各浏览器的返回值的差异也较大。

解决方案

当出现页面垂直滚动条的时候尽量使用 'document.body.scrollHeight' 获取页面滚动条的高度。

当页面没有生成垂直滚动条时,避免使用 document.documentElement.scrollHeight 及 document.body.scrollHeight 获取某种高度,此时应使用 offsetHeight。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.3
Chrome 5.0.366.2 dev
Safari 4.0.5
Opera 10.51
测试页面: iframe1.html
iframe2.html
本文更新时间: 2010-07-14

关键字

scrollHeight 滚动条 高度