计算跨浏览器 iframe 高度

Posted

技术标签:

【中文标题】计算跨浏览器 iframe 高度【英文标题】:Computing a cross-browser iframe height 【发布时间】:2010-09-17 11:43:00 【问题描述】:

在我的 javascript 体验中,最困难的问题之一是正确(即“跨浏览器”)计算 iframe 高度。 在我的应用程序中,我有很多动态生成的 iframe,我希望它们都在加载事件结束时进行某种自动调整大小以调整它们的高度和宽度。

height 计算的情况下,我的最佳解决方案如下(在 jQuery 的帮助下):

function getDocumentHeight(doc) 
  var mdoc = doc || document;
  if (mdoc.compatMode=='CSS1Compat')        
      return mdoc.body.offsetHeight;
  
  else 
    if ($.browser.msie)
      return mdoc.body.scrollHeight;
    else  
      return Math.max($(mdoc).height(), $(mdoc.body).height());
  

我搜索了互联网但没有成功。我还测试了雅虎库,它有一些文档和视口尺寸的方法,但并不令人满意。 我的解决方案效果不错,但有时它会计算出更高的高度。 我已经研究并测试了大量关于 Firefox/IE/Safari 中文档高度的属性:documentElement.clientHeight, documentElement.offsetHeight, documentElement.scrollHeight, body.offsetHeight, body.scrollHeight, ... 此外,jQuery 在各种浏览器中没有连贯的行为,调用 $(document.body).height(), $('html', doc).height(), $(window).height()

我不仅在加载事件结束时调用上述函数,而且在动态插入 DOM 元素或隐藏或显示元素的情况下也调用。这种情况有时会破坏仅在加载事件中有效的代码。

有人有真正的跨浏览器(至少是 Firefox/IE/Safari)解决方案吗?一些提示或提示?

【问题讨论】:

我现在正在处理这个问题。你找到解决办法了吗? 【参考方案1】:

虽然我喜欢你的解决方案,但我一直发现 IFRAME 带来的麻烦多于其价值。

为什么? 1、尺码问题。 2. iframe 需要担心 src 属性。即绝对路径。 3. 页面的额外复杂性。

我的解决方案 - 通过 AJAX 调用动态加载的 DIV。 DIV 将自动调整大小。尽管 AJAX 代码需要 javascript 工作(可以通过框架完成),但它们与站点所在的位置相关。 3 是一个洗牌,你在交易页面的复杂性直到 javascript。

而不是

执行 ajax 调用以用数据填充 mystuff div 并让浏览器担心它。

【讨论】:

我考虑过 DIV 的可能性,但我不知道 ID(DOM 元素的)问题的简单解决方案:共享相同的命名空间,DIV 可能有很多 id 冲突。考虑到我同时打开了许多 iframe。不过,您的解决方案值得仔细考虑。 您不能从外部站点 AJAX 加载内容;这是浏览器安全违规(跨站点脚本)。 可能是唯一允许加载外部内容的客户端解决方案。 关于 x-site 项目的观点非常好,但是,如果我真的需要这些数据,我会从服务器“反弹”它。即页面进行调用,服务器构建页面,包括其他“外部”页面,然后将其返回给原始客户端。我有一个客户想要嵌入视频,为了避免跨站点,服务器将其拉取暂时存储并将所有内容返回给客户端。 @jim - 我对这种方法的问题是我正在加载可能会或可能不会半损坏的 HTML。使用 iframe 可以限制不良标记对页面其余部分的影响。 您可以使用 JSONP 从另一个域加载数据。【参考方案2】:

这已经有一段时间没有公认的答案了,所以我想贡献我在研究后最终得到的解决方案。 这是跨浏览器和跨域(例如,当 iframe 指向来自不同域的内容时)

我最终使用了包裹在 jQuery pluging 中的 html5 的消息传递机制,这使得它可以使用各种方法(其中一些在此线程中描述)与旧版浏览器兼容。

最终的解决方案很简单。

在主机(父)页面上:

// executes when a message is received from the iframe, to adjust 
// the iframe's height
    $.receiveMessage(
        function( event )
            $( 'my_iframe' ).css(
                height: event.data
            );
    );

// Please note this function could also verify event.origin and other security-related checks.

在 iframe 页面上:

$(function()

    // Sends a message to the parent window to tell it the height of the 
    // iframe's body

    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);

    $.postMessage(
        $('body').outerHeight( true ) + 'px',
        '*',
        target
    );

);

我已经在 XP 和 W7 上的 Chrome 13+、Firefox 3.6+、IE7、8 和 9 以及 OSX 和 W7 上的 safari 上进行了测试。 ;)

【讨论】:

【参考方案3】:

因为在您的示例中,您正在访问文档inside IFRAME,我猜您是在谈论了解文档的高度而不是框架本身的高度。此外,这意味着内容来自您自己的网站,并且您可以控制其内容。

那么,为什么不简单地在内容周围放置一个 DIV,然后使用该 DIV 的 clientHeight?

您在 IFRAME 中加载的代码:

...
<body>
  <div id="content">
  ...
  </div>
</body>

父文档:

 function getDocumentHeight(mdoc) 
    return mdoc.getElementById("content").clientHeight;
 

顺便说一句,您的示例函数的这一部分没有意义,因为“文档”没有引用 IFRAME: var mdoc = doc || document;

【讨论】:

【参考方案4】:

这是一个似乎可行的解决方案。基本上,在大多数情况下,scrollHeight 是正确的值。但是,在 IE(特别是 6 和 7)中,如果内容只是包含在文本节点中,则不会计算高度,而是默认为 CSS 中设置的高度或 iframe 上的“高度”属性。这是通过反复试验发现的,因此值得一试。

function getDocumentHeight(doc) 
  var mdoc = doc || document; 
  var docHeight = mdoc.body.scrollHeight;

  if ($.browser.msie) 
      // IE 6/7 don't report body height correctly.  
      // Instead, insert a temporary div containing the contents.

      var child = $("<div>" + mdoc.body.innerHTML + "</div>", mdoc);
      $("body", mdoc).prepend(child);
      docHeight = child.height();
      child.remove();
  

  return docHeight;

【讨论】:

【参考方案5】:

我发现此解决方案适用于 ie 6+、ff 3.5+、safari 4+。我正在创建 iframe 并将其附加到文档中。以下代码在 jQuery 的 load 事件结束后执行一些其他 dom 操作。由于加载事件中发生了额外的 dom 操作,因此我需要超时。

// sizing - slight delay for good scrollheight
setTimeout(function() 
   var intContentHeight = objContentDoc.body.scrollHeight;
   var $wrap = $("#divContentWrapper", objContentFrameDoc);
   var intMaxHeight = getMaxLayeredContentHeight($wrap);
   $this.height(intContentHeight > intMaxHeight ? intMaxHeight : intContentHeight);

   // animate
   fireLayeredContentAnimation($wrap);
, 100);

我需要考虑一些尺寸限制,这就是 getMaxLayeredContentHeight 调用正在为我检查的内容。希望对您有所帮助。

【讨论】:

【参考方案6】:

Here's a script 根据内部主体的高度调整 iFrame 的大小。

【讨论】:

以上是关于计算跨浏览器 iframe 高度的主要内容,如果未能解决你的问题,请参考以下文章

前端开发跨浏览器计算页面大小滚动高度

检测 Iframe 内容何时加载(跨浏览器)

允许 iframe 成为全屏、跨浏览器

将 IFrame 设置为“about:blank”的跨浏览器方式?

跨所有浏览器从 iFrame 传递消息

允许iframe成为全屏,跨浏览器