【问题标题】:make iframe height dynamic based on content inside- JQUERY/Javascript根据里面的内容使 iframe 高度动态化 - JQUERY/Javascript
【发布时间】:2015-03-06 07:03:47
【问题描述】:

我正在 iframe 中加载一个 aspx 网页。 iframe 中的内容可以比 iframe 的高度更高。 iframe 不应有滚动条。

我在 iframe 中有一个包装器 div 标记,它基本上是所有内容。我写了一些 jQuery 来实现调整大小:

$("#TB_window", window.parent.document).height($("body").height() + 50);

在哪里 TB_window 是包含 Iframe 的 div。

body - iframe中aspx的body标签。

此脚本附加到 iframe 内容。我从父页面获取TB_window 元素。虽然这在 Chrome 上运行良好,但 TB_window 在 Firefox 中崩溃。我真的很困惑/不知为什么会发生这种情况。

【问题讨论】:

  • 那个.aspx iframe页面来自同一个域名?
  • 你能检查$("body").height()在firefox中有值吗?
  • 是的..iframe 与容器页面在同一个域中
  • @MichaelLWatson 看起来萤火虫监视窗口的身体高度值为 0...Chrome 确实有一个值
  • Angular iFrame 自动高度示例:gitlab.com/reduardo7/angular-iframe-auto-height

标签: javascript jquery asp.net iframe


【解决方案1】:

您可以使用以下方法检索IFRAME 内容的高度: contentWindow.document.body.scrollHeight

IFRAME 加载后,您可以通过以下操作更改高度:

<script type="text/javascript">
  function iframeLoaded() {
      var iFrameID = document.getElementById('idIframe');
      if(iFrameID) {
            // here you can make the height, I delete it first, then I make it again
            iFrameID.height = "";
            iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
      }   
  }
</script>   

然后,在IFRAME 标签上,像这样连接处理程序:

<iframe id="idIframe" onload="iframeLoaded()" ...

我前段时间遇到过一种情况,在其中发生表单提交后,我还需要从IFRAME 本身调用iframeLoaded。您可以通过在IFRAME 的内容脚本中执行以下操作来完成此操作:

parent.iframeLoaded();

【讨论】:

  • 不支持跨域。
  • @Soumya 跨域与这段代码无关。您使用命令绕过了一个安全问题。
  • @Soumya 查找X-FRAME-OPTIONS 添加一行:Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");response.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
  • 这解决了跨域 iframe 大小问题github.com/davidjbradshaw/iframe-resizer
  • @DavidBradshaw - 你有很好的脚本,它甚至可以跨域工作,但 CORS 最常用的场景是当你无权访问远程加载的页面时。我正在尝试使用您的脚本将 google 文档表单加载到网站(嵌入式)中,但这并不能解决问题;(
【解决方案2】:

对 Aristos 的回答略有改进...

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
  }
</script>  

然后在你的 iframe 中声明如下:

<iframe onload="resizeIframe(this)" ...

有两个小的改进:

  1. 您不需要通过 document.getElementById 获取元素 - 因为您已经在 onload 回调中拥有它。
  2. 如果您要在下一条语句中重新分配iframe.height = "",则无需设置它。在处理 DOM 元素时,这样做实际上会产生开销。

编辑: 如果框架中的内容总是在变化,那么调用:

parent.resizeIframe(this.frameElement); 

来自更新后的 iframe。适用于同一来源。

或自动检测:

  // on resize
  this.container = this.frameElement.contentWindow.document.body;

  this.watch = () => {
    cancelAnimationFrame(this.watcher);

    if (this.lastScrollHeight !== container.scrollHeight) {
      parent.resizeIframeToContentSize(this.frameElement);  
    }
    this.lastScrollHeight = container.scrollHeight;
    this.watcher = requestAnimationFrame(this.watch);
  };
  this.watcher = window.requestAnimationFrame(this.watch);

【讨论】:

  • 如果框架中的内容一直在变化,你会怎么做?
  • 为此...解决方案是使用postMessage和receiveMessage。我使用github.com/jeffomatic/nojquery-postmessage 解决了这个问题
  • 这个想法是计算新的高度并向需要接收消息的父框架发送消息并相应地调整iframe的高度。
  • 对我来说总是一些像素短,所以我想出了这个:function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
【解决方案3】:

我发现接受的答案还不够,因为 X-FRAME-OPTIONS: Allow-From isn't supported in safari or chrome。而是采用了不同的方法,在 Disqus 的 Ben Vinegar 给出的presentation 中找到。这个想法是给父窗口添加一个事件监听器,然后在 iframe 内部,使用 window.postMessage 向父窗口发送一个事件,告诉它做某事(调整 iframe 的大小)。

所以在父文档中,添加一个事件监听器:

window.addEventListener('message', function(e) {
  var $iframe = jQuery("#myIframe");
  var eventName = e.data[0];
  var data = e.data[1];
  switch(eventName) {
    case 'setHeight':
      $iframe.height(data);
      break;
  }
}, false);

在 iframe 中,编写一个函数来发布消息:

function resize() {
  var height = document.getElementsByTagName("html")[0].scrollHeight;
  window.parent.postMessage(["setHeight", height], "*"); 
}

最后,在 iframe 中,在 body 标签中添加一个 onLoad 来触发 resize 函数:

<body onLoad="resize();">

【讨论】:

  • 为了让这对我有用,我不得不将“window.parent”更改为“parent”。
  • 太棒了!但它只加载一次高度。如果你想让 iframe 真正响应,我更喜欢每秒调用 resize 方法,如下所示:setInterval(resize, 1000);
【解决方案4】:

将此添加到 iframe,这对我有用:

onload="this.height=this.contentWindow.document.body.scrollHeight;"

如果你使用 jQuery,试试这个代码:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"

【讨论】:

    【解决方案5】:

    您可以查看四种不同的属性来获取 iFrame 中内容的高度。

    document.documentElement.scrollHeight
    document.documentElement.offsetHeight
    document.body.scrollHeight
    document.body.offsetHeight
    

    遗憾的是,他们都可以给出不同的答案,而且这些在浏览器之间是不一致的。如果将正文边距设置为 0,则 document.body.offsetHeight 给出最佳答案。要获得正确的值,请尝试此功能;它取自 iframe-resizer 库,该库还负责在内容更改或调整浏览器大小时保持 iFrame 的正确大小。

    function getIFrameHeight(){
        function getComputedBodyStyle(prop) {
            function getPixelValue(value) {
                var PIXEL = /^\d+(px)?$/i;
    
                if (PIXEL.test(value)) {
                    return parseInt(value,base);
                }
    
                var 
                    style = el.style.left,
                    runtimeStyle = el.runtimeStyle.left;
    
                el.runtimeStyle.left = el.currentStyle.left;
                el.style.left = value || 0;
                value = el.style.pixelLeft;
                el.style.left = style;
                el.runtimeStyle.left = runtimeStyle;
    
                return value;
            }
    
            var 
                el = document.body,
                retVal = 0;
    
            if (document.defaultView && document.defaultView.getComputedStyle) {
                retVal =  document.defaultView.getComputedStyle(el, null)[prop];
            } else {//IE8 & below
                retVal =  getPixelValue(el.currentStyle[prop]);
            } 
    
            return parseInt(retVal,10);
        }
    
        return document.body.offsetHeight +
            getComputedBodyStyle('marginTop') +
            getComputedBodyStyle('marginBottom');
    }
    

    【讨论】:

    • 这不适用于“汇总”的项目,例如数据表或浮动 div。高度基于正常的展开高度,而不是最终高度。
    • @djack109 您的 CSS 中的某些内容很可能会阻止页面上的元素缩小
    【解决方案6】:

    您还可以在 resizeIframe 中添加一个重复的 requestAnimationFrame(例如来自@BlueFish 的回答),它总是在浏览器绘制布局之前被调用,并且您可以在 iframe 的内容改变其高度时更新 iframe 的高度。例如输入表单、延迟加载的内容等。

    <script type="text/javascript">
      function resizeIframe(iframe) {
        iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
        window.requestAnimationFrame(() => resizeIframe(iframe));
      }
    </script>  
    
    <iframe onload="resizeIframe(this)" ...
    

    您的回调应该足够快,不会对您的整体表现产生太大影响

    【讨论】:

    • 这是一个非常巧妙的解决方案,从最初的测试开始,效果非常好。我会对使用它的性能影响感兴趣。
    • 刚刚遇到一个案例Uncaught TypeError: Cannot read property 'scrollHeight' of null,因为bodynull,但是它通常可以工作。
    【解决方案7】:

    其他答案对我不起作用,所以我做了一些更改。希望这会有所帮助

    $('#iframe').on("load", function() {
        var iframe = $(window.top.document).find("#iframe");
        iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
    });
    

    【讨论】:

      【解决方案8】:

      以防万一这对任何人都有帮助。我拉着头发试图让它工作,然后我注意到 iframe 有一个高度为 100% 的类条目。当我删除它时,一切都按预期工作。所以,请检查是否有任何 css 冲突。

      【讨论】:

        【解决方案9】:

        我正在使用 jQuery,下面的代码为我工作,

        var iframe = $(window.top.document).find("#iframe_id_here");
        iframe.height(iframe.contents().height()+'px' );
        

        【讨论】:

          【解决方案10】:

          您可以在这里参考相关问题 - How to make width and height of iframe same as its parent div?

          设置动态高度 -

          1. 我们需要与跨域 iFrame 和父级通信
          2. 然后我们可以将 iframe 的滚动高度/内容高度发送到父窗口

          和代码 - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8

          【讨论】:

            【解决方案11】:

            我发现最简单的方法不是使用 javscript/jquery:

            &lt;iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"&gt;&lt;/iframe&gt;

            这里 1vh = 浏览器窗口高度的 1%。所以要设置的高度的理论值是 100vh,但实际上 98vh 起到了神奇的作用。

            【讨论】:

            • 这没有考虑 iframe 的内容高度。
            • 当你没有一个简单的方法来解决跨域戏剧时,这已经足够接近了......
            【解决方案12】:

            所有其他答案都是正确的,但是如果 iframe 具有一些动态内容,例如稍后加载并动态更改 iframe 滚动高度的地图,该怎么办。我就是这样实现的。

            var iFrameID = document.getElementById('idIframe');
            
            intval =  setInterval(function(){
            if(iFrameID.scrollHeight == iFrameID.contentWindow.document.body.scrollHeight){
                 clearInterval(intval);
            }else{
               iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
              }
            },500)
            

            我只是将代码封装在 setInterval 中,它将 iframe 滚动高度与 iframe 内容滚动高度相匹配,然后清除间隔。

            【讨论】:

              【解决方案13】:

              在我的项目中,有一个要求是我们在加载时制作动态屏幕,如仪表板对齐,如果用户最大化或调整浏览器窗口的大小,它应该显示在整个页面上并且应该动态调整。 为此,我创建了 url 并使用 iframe 打开了用 cognos BI 编写的动态报告之一。在 jsp 中,我们必须嵌入 BI 报告。我已经使用 iframe 将此报告嵌入到 jsp 中。以下代码适用于我的情况。

              <iframe src= ${cognosUrl} onload="this.style.height=(this.contentDocument.body.scrollHeight+30) +'px';" scrolling="no" style="width: 100%; min-height: 900px; border: none; overflow: hidden; height: 30px;"></iframe>
              

              【讨论】:

              • 什么都不做,在控制台中说this.contentDocument is null
              【解决方案14】:

              我发现特洛伊的答案不起作用。这是为 ajax 重新编写的相同代码:

              $.ajax({                                      
                  url: 'data.php',    
                  dataType: 'json',                             
              
                  success: function(data)
                  {
                      // Put the data onto the page
              
                      // Resize the iframe
                      var iframe = $(window.top.document).find("#iframe");
                      iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
                  }
              });
              

              【讨论】:

                【解决方案15】:

                添加到底部似乎被切断的窗口块,尤其是当你没有滚动时,我使用了:

                function resizeIframe(iframe) {
                    var addHeight = 20; //or whatever size is being cut off
                    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
                  }
                

                【讨论】:

                  【解决方案16】:

                  当您需要一个没有 jquery 的解决方案时,这个很有用。在这种情况下,您应该尝试添加一个容器并以百分比为其设置填充

                  HTML 示例代码:

                  <div class="iframecontainer">
                      <iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
                  </div>
                  

                  CSS 示例代码:

                  .iframeclass{
                      position: absolute;
                      top: 0;
                      width: 100%;
                  }
                  
                  .iframecontainer{
                      position: relative;
                      width: 100%;
                      height: auto;
                      padding-top: 61%;
                  }
                  

                  【讨论】:

                    【解决方案17】:

                    简单的解决方案是测量内容区域的宽度和高度,然后使用这些测量值来计算底部填充百分比。

                    在本例中,测量值为 1680 x 720 像素,因此底部的内边距为 720 / 1680 = 0.43 * 100,即为 43%。

                    .canvas-container {    
                        position: relative;
                        padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
                        height: 0;
                        overflow: hidden;   
                    }
                    
                    .canvas-container iframe {    
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;   
                    }
                    

                    【讨论】:

                      【解决方案18】:

                      对 BlueFish 的稍微改进的答案...

                      function resizeIframe(iframe) {
                          var padding = 50;
                          if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
                              iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
                          else
                              iframe.height = (window.innerHeight - padding) + "px";
                      }
                      

                      这考虑了 Windows 屏幕(浏览器、手机)的高度,这对于响应式设计和具有巨大高度的 iframe 非常有用。 填充表示在 iframe 穿过整个屏幕的情况下您想要在 iframe 上方和下方的填充。

                      【讨论】:

                        【解决方案19】:
                        jQuery('.home_vidio_img1 img').click(function(){
                            video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
                            jQuery(this).replaceWith(video);
                        });
                        
                        jQuery('.home_vidio_img2 img').click(function(){
                            video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
                            jQuery('.home_vidio_img1 img').replaceWith(video);
                            jQuery('.home_vidio_img1 iframe').replaceWith(video);
                        });
                        
                        jQuery('.home_vidio_img3 img').click(function(){
                            video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
                            jQuery('.home_vidio_img1 img').replaceWith(video);
                            jQuery('.home_vidio_img1 iframe').replaceWith(video);
                        });
                        
                        jQuery('.home_vidio_img4 img').click(function(){
                            video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
                            jQuery('.home_vidio_img1 img').replaceWith(video);
                            jQuery('.home_vidio_img1 iframe').replaceWith(video);
                        });
                        

                        【讨论】:

                          【解决方案20】:

                          使用 PHP htmlspecialchars() 的示例 + 检查高度是否存在并且 > 0:

                          $my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
                          $iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
                          

                          【讨论】:

                            【解决方案21】:
                            $(document).height() // - $('body').offset().top
                            

                            和/或

                            $(window).height()
                            

                            查看堆栈溢出问题How to get the height of a body element

                            试试这个在jQuery中找到body的高度:

                            if $("body").height()
                            

                            Firebug 没有值。也许这就是问题所在。

                            【讨论】:

                            • 我都试过了......它仍然发生在 Firefox 上。 Firefox 不知何故无法在 iframe 上获得 window.height()。正如我所提到的,脚本附加到 iframe 内容中,我在 document.ready() 函数中调用它
                            【解决方案22】:

                            只要使 iframe 容器位置:absolute 并且 iframe 会根据其内容自动改变其高度

                            <style>
                               .iframe-container {
                                   display: block;
                                   position: absolute;
                                   /*change position as you need*/
                                   bottom: 0;
                                   left: 0;
                                   right: 0;
                                   top: 0;
                               }
                               iframe {
                                   margin: 0;
                                   padding: 0;
                                   border: 0;
                                   width: 100%;
                                   background-color: #fff;
                               }
                             </style>
                             <div class="iframe-container">
                                 <iframe src="http://iframesourcepage"></iframe>
                             </div>
                            

                            【讨论】:

                              猜你喜欢
                              • 2015-04-14
                              • 1970-01-01
                              • 2012-07-29
                              • 2012-05-21
                              • 2011-11-17
                              • 1970-01-01
                              • 2012-01-06
                              • 2013-08-02
                              相关资源
                              最近更新 更多