首页 文章

根据内容调整iframe大小

提问于
浏览
486

我正在开发类似iGoogle的应用程序 . 来自其他应用程序(在其他域上)的内容使用iframe显示 .

如何调整iframe的大小以适应iframe内容的高度?

我试图破译谷歌使用的javascript,但是它被混淆了,到目前为止搜索网络已经没有结果 .

Update: 请注意,内容是从其他域加载的,因此same-origin policy适用 .

20 回答

  • 6

    此答案仅适用于使用Bootstrap的网站 . Bootstrap的响应式嵌入功能完成了这项工作 . 它基于内容的宽度(而不是高度) .

    <!-- 16:9 aspect ratio -->
    <div class="embed-responsive embed-responsive-16by9">
      <iframe class="embed-responsive-item" src="http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe>
    </div>
    

    jsfiddle:http://jsfiddle.net/00qggsjj/2/

    http://getbootstrap.com/components/#responsive-embed

  • 2

    我们遇到了这种类型的问题,但与您的情况略有相反 - 我们将iframed内容提供给其他域上的网站,因此same origin policy也是一个问题 . 经过长达数小时的拖网搜索后,我们最终找到了一个(有点......)可行的解决方案,您可以根据自己的需要进行调整 .

    围绕相同的原始策略有一种方法,但它需要对iframed内容和框架页面进行更改,因此如果您无法双方请求更改,则此方法对您来说不是很有用,我耽心 .

    有一个浏览器怪癖,它允许我们绕过相同的原始政策 - javascript可以与其自己的域上的页面进行通信,也可以与已经有iframed的页面进行通信,但从不与其进行框架化的页面进行通信,例如,如果你有:

    www.foo.com/home.html, which iframes
     |-> www.bar.net/framed.html, which iframes
         |-> www.foo.com/helper.html
    

    然后 home.html 可以与 framed.html (iframed)和 helper.html (同一域)进行通信 .

    Communication options for each page:
     +-------------------------+-----------+-------------+-------------+
     |                         | home.html | framed.html | helper.html |
     +-------------------------+-----------+-------------+-------------+
     | www.foo.com/home.html   |    N/A    |     YES     |     YES     |
     | www.bar.net/framed.html |    NO     |     N/A     |     YES     |
     | www.foo.com/helper.html |    YES    |     YES     |     N/A     |
     +-------------------------+-----------+-------------+-------------+
    

    framed.html 可以发送消息到 helper.html (iframed)但不能发送 home.html (子节点不能与父节点进行跨域通信) .

    这里的关键是 helper.html 可以从 framed.html 接收消息,而 can also communicate 可以接收 home.html .

    基本上,当 framed.html 加载时,它会计算出自己的高度,告诉 helper.html ,它将消息传递给 home.html ,然后可以调整 framed.html 所在的iframe的大小 .

    我们发现将消息从 framed.html 传递到 helper.html 的最简单方法是通过URL参数 . 为此, framed.html 具有指定了 src='' 的iframe . 当它的 onload 触发时,它会计算自己的高度,并在此时将iframe的src设置为 helper.html?height=N

    There's an explanation here facebook如何处理它,这可能比我的上面稍微清楚一点!


    Code

    www.foo.com/home.html 中,需要以下javascript代码(这可以从任何域上的.js文件加载,顺便提一下......):

    <script>
      // Resize iframe to full height
      function resizeIframe(height)
      {
        // "+60" is a general rule of thumb to allow for differences in
        // IE & and FF height reporting, can be adjusted as required..
        document.getElementById('frame_name_here').height = parseInt(height)+60;
      }
    </script>
    <iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>
    

    www.bar.net/framed.html

    <body onload="iframeResizePipe()">
    <iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe>
    
    <script type="text/javascript">
      function iframeResizePipe()
      {
         // What's the page height?
         var height = document.body.scrollHeight;
    
         // Going to 'pipe' the data to the parent through the helpframe..
         var pipe = document.getElementById('helpframe');
    
         // Cachebuster a precaution here to stop browser caching interfering
         pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();
    
      }
    </script>
    

    www.foo.com/helper.html 的内容:

    <html> 
    <!-- 
    This page is on the same domain as the parent, so can
    communicate with it to order the iframe window resizing
    to fit the content 
    --> 
      <body onload="parentIframeResize()"> 
        <script> 
          // Tell the parent iframe what height the iframe needs to be
          function parentIframeResize()
          {
             var height = getParam('height');
             // This works as our parent's parent is on our domain..
             parent.parent.resizeIframe(height);
          }
    
          // Helper function, parse param from request string
          function getParam( name )
          {
            name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
            var regexS = "[\\?&]"+name+"=([^&#]*)";
            var regex = new RegExp( regexS );
            var results = regex.exec( window.location.href );
            if( results == null )
              return "";
            else
              return results[1];
          }
        </script> 
      </body> 
    </html>
    
  • 4

    这有点棘手,因为您必须知道iframe页面何时加载,这在您无法控制其内容时会很困难 . 它可以为iframe添加一个onload处理程序,但我在过去尝试过它,它在浏览器中的行为有很大不同(不要猜猜谁最烦人......) . 您可能必须向执行调整大小的iframe页面添加一个函数,并将一些脚本注入到侦听加载事件或调整事件大小的内容中,然后调用前一个函数 . 我正在考虑为页面添加一个函数,因为你想确保它的安全,但我不知道它会有多容易 .

  • -4

    http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html上的解决方案效果很好(使用jQuery):

    <script type=”text/javascript”>
      $(document).ready(function() {
        var theFrame = $(”#iFrameToAdjust”, parent.document.body);
        theFrame.height($(document.body).height() + 30);
      });
    </script>
    

    我不知道你需要增加30个长度...... 1对我有用 .

    FYI :如果您的iFrame上已经有"height"属性,则只需添加style = "height: xxx" . 这可能不是你想要的 .

  • 0

    可能有点晚了,因为所有其他答案都比较旧:-)但是......这是我的解决方案 . 在实际的FF,Chrome和Safari 5.0中测试过 .

    CSS:

    iframe {border:0; overflow:hidden;}
    

    JavaScript的:

    $(document).ready(function(){
        $("iframe").load( function () {
            var c = (this.contentWindow || this.contentDocument);
            if (c.document) d = c.document;
            var ih = $(d).outerHeight();
            var iw = $(d).outerWidth();
            $(this).css({
                height: ih,
                width: iw
            });
        });
    });
    

    希望这会对任何人有所帮助 .

  • 8

    这里's a jQuery approach that adds the info in json via the src attribute of the iframe. Here'是一个演示,调整大小并滚动这个窗口..带有json的结果url看起来像这样...... http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight:571}#

    这是源代码小提琴http://jsfiddle.net/zippyskippy/RJN3G/

    function updateLocation(){
    
        var loc = window.location.href;
        window.location.href = loc.replace(/#{.*}#/,"") 
            + "#{docHeight:"+$(document).height() 
            + ",windowHeight:"+$(window).height()
            + ",scrollHeight:"+$(window).scrollTop()
            +"}#";
    
    };
    
    //setInterval(updateLocation,500);
    
    $(window).resize(updateLocation);
    $(window).scroll(updateLocation);
    
  • 2

    获取iframe内容高度然后将其提供给此iframe

    var iframes = document.getElementsByTagName("iframe");
     for(var i = 0, len = iframes.length; i<len; i++){
          window.frames[i].onload = function(_i){
               return function(){
                         iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px";
                         }
          }(i);
     }
    
  • 0
    <html>
    <head>
    <script>
    function frameSize(id){
    var frameHeight;
    
    document.getElementById(id).height=0 + "px";
    if(document.getElementById){
        newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;    
    }
    
    document.getElementById(id).height= (frameHeight) + "px";
    }
    </script>
    </head>
    
    <body>
    
    <iframe id="frame"  src="startframe.html" frameborder="0" marginheight="0" hspace=20     width="100%" 
    
    onload="javascript:frameSize('frame');">
    
    <p>This will work, but you need to host it on an http server, you can do it locally.    </p>
    </body>
    </html>
    
  • 40

    这个我相信的东西应该工作 .

    parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;
    

    在iframe内容中加载您的身体onload .

  • 0

    https://developer.mozilla.org/en/DOM/window.postMessage

    window.postMessage()window.postMessage是一种安全启用跨源通信的方法 . 通常,当且仅当执行它们的页面位于具有相同协议(通常是http),端口号(80是http的默认值)和主机(模数)的位置时,才允许不同页面上的脚本相互访问 . document.domain由两个页面设置为相同的值) . window.postMessage提供了一种受控机制,可以在正确使用时以安全的方式规避此限制 . 总结window.postMessage,当被调用时,会导致在任何必须执行的挂起脚本完成时在目标窗口调度MessageEvent(例如,如果从事件处理程序调用window.postMessage,之前设置的挂起超时等,则保留事件处理程序等) ) . MessageEvent具有类型消息,一个data属性,设置为提供给window.postMessage的第一个参数的字符串值,一个origin属性对应于窗口中主文档的原点在调用window.postMessage时调用window.postMessage,并调用一个source属性,该属性是调用window.postMessage的窗口 . (事件的其他标准属性与其预期值一起出现 . )

    iFrame-Resizer库使用postMessage来保持iFrame大小与其内容一致,以及MutationObserver来检测内容的更改并且不依赖于jQuery .

    https://github.com/davidjbradshaw/iframe-resizer

    jQuery:跨域脚本编写的好处

    http://benalman.com/projects/jquery-postmessage-plugin/

    有调整iframe窗口大小的演示......

    http://benalman.com/code/projects/jquery-postmessage/examples/iframe/

    本文介绍如何删除对jQuery的依赖... Plus有很多有用的信息和其他解决方案的链接 .

    http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/

    准噶尔人的例子......

    http://onlineaspect.com/uploads/postmessage/parent.html

    关于window.postMessage的HTML 5工作草案

    http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages

    John Resig关于跨窗口消息传递

    http://ejohn.org/blog/cross-window-messaging/

  • -2

    使用jQuery的最简单方法:

    $("iframe")
    .attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
    .load(function() {
        $(this).css("height", $(this).contents().height() + "px");
    });
    
  • 0

    iGoogle小工具必须积极实施调整大小,因此我的猜测是在跨域模型中,如果没有远程内容以某种方式参与,则无法执行此操作 . 如果您的内容可以使用典型的跨域通信技术将具有新大小的消息发送到容器页面,那么其余的很简单 .

  • 0

    我有一个简单的解决方案,并要求您确定链接的宽度和高度,请尝试(它适用于大多数浏览器):

    <a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>
    
  • 0

    在加载时使用jquery(跨浏览器):

    <iframe src="your_url" marginwidth="0"  marginheight="0" scrolling="No" frameborder="0"  hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%"  width="100%"></iframe>
    
    function loaderIframe(){
    var heightIframe = $('#containiframe').contents().find('body').height();
    $('#frame').css("height", heightFrame);
     }
    

    在响应式页面中调整大小:

    $(window).resize(function(){
    if($('#containiframe').length !== 0) {
    var heightIframe = $('#containiframe').contents().find('body').height();
     $('#frame').css("height", heightFrame);
    }
    });
    
  • 1

    使用jQuery:

    parent.html

    <body>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <style>
    iframe {
        width: 100%;
        border: 1px solid black;
    }
    </style>
    <script>
    function foo(w, h) {
        $("iframe").css({width: w, height: h});
        return true;  // for debug purposes
    }
    </script>
    <iframe src="child.html"></iframe>
    </body>
    

    child.html

    <body>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
    $(function() {
        var w = $("#container").css("width");
        var h = $("#container").css("height");
    
        var req = parent.foo(w, h);
        console.log(req); // for debug purposes
    });
    </script>
    <style>
    body, html {
        margin: 0;
    }
    #container {
        width: 500px;
        height: 500px;
        background-color: red;
    }
    </style>
    <div id="container"></div>
    </body>
    
  • -2

    如果您不需要处理来自不同域的iframe内容,请尝试使用此代码,它将完全解决问题并且很简单:

    <script language="JavaScript">
    <!--
    function autoResize(id){
        var newheight;
        var newwidth;
    
        if(document.getElementById){
            newheight=document.getElementById(id).contentWindow.document .body.scrollHeight;
            newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth;
        }
    
        document.getElementById(id).height= (newheight) + "px";
        document.getElementById(id).width= (newwidth) + "px";
    }
    //-->
    </script>
    
    <iframe src="usagelogs/default.aspx" width="100%" height="200px" id="iframe1" marginheight="0" frameborder="0" onLoad="autoResize('iframe1');"></iframe>
    
  • 2

    我正在实施ConroyP的框架帧解决方案来替换基于设置document.domain的解决方案,但发现在不同的浏览器中正确确定iframe内容的高度非常困难(现在用FF11,Ch17和IE9进行测试) ) .

    ConroyP使用:

    var height = document.body.scrollHeight;
    

    但这只适用于初始页面加载 . 我的iframe有动态内容,我需要在某些事件上调整iframe的大小 .

    我最终做的是为不同的浏览器使用不同的JS属性 .

    function getDim () {
        var body = document.body,
            html = document.documentElement;
    
        var bc = body.clientHeight;
        var bo = body.offsetHeight;
        var bs = body.scrollHeight;
        var hc = html.clientHeight;
        var ho = html.offsetHeight;
        var hs = html.scrollHeight;
    
        var h = Math.max(bc, bo, bs, hc, hs, ho);
    
        var bd = getBrowserData();
    
        // Select height property to use depending on browser
        if (bd.isGecko) {
            // FF 11
            h = hc;
        } else if (bd.isChrome) {
            // CH 17
            h = hc;
        } else if (bd.isIE) {
            // IE 9
            h = bs;
        }
    
        return h;
    }
    

    getBrowserData()是Ext Core的http://docs.sencha.com/core/source/Ext.html#method-Ext-apply的浏览器检测功能"inspired"

    这适用于FF和IE,但后来Chrome出现了问题 . 其中一个是计时问题,显然需要Chrome一段时间来设置/检测iframe的高度 . 如果iframe高于内容,则Chrome也不会正确返回iframe中内容的高度 . 当高度降低时,这不适用于动态内容 .

    为了解决这个问题,我总是在检测内容的高度之前将iframe设置为较低的高度,然后将iframe高度设置为正确的值 .

    function resize () {
        // Reset the iframes height to a low value.
        // Otherwise Chrome won't detect the content height of the iframe.
        setIframeHeight(150);
    
        // Delay getting the dimensions because Chrome needs
        // a few moments to get the correct height.
        setTimeout("getDimAndResize()", 100);
    }
    

    代码没有优化,它来自我的开发测试:)

    希望有人觉得这很有帮助!

  • 573

    这是一个使用动态生成的样式表的简单解决方案,该样式表由与iframe内容相同的服务器提供 . 很简单,样式表“知道”iframe中的内容,并且知道用于设置iframe样式的尺寸 . 这绕过了相同的原始政策限制 .

    http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/

    所以提供的iframe代码会有一个伴随的样式表,如此...

    <link href="http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel="stylesheet" type="text/css" />
 <iframe id="iframe_widget" src="http://your.site/path/to/content?content_id=1234" frameborder="0" width="100%" scrolling="no"></iframe>

    这确实需要服务器端逻辑能够计算iframe的呈现内容的维度 .

  • 79

    如果要缩小网页以使其适合iframe大小:

    • 您应该调整 iframe 的大小以使其适合内容

    • 然后你应该用加载的网页内容缩小整个iframe

    这是一个例子:

    <div id="wrap">
       <IFRAME ID="frame" name="Main" src ="http://www.google.com" />
    </div>
    

    <style type="text/css">
        #wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; }
        #frame { width: 900px; height: 600px; border: 1px solid black; }
        #frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-origin: 0 0; }
    </style>
    
  • 1

    最后,我找到了一些其他解决方案,使用 window.postMessage(message, targetOrigin); 从iframe向父网站发送数据 . 在这里,我解释我是如何做的 .

    网站A = http://foo.com网站B = http://bar.com

    SiteB正在siteA网站内加载

    SiteB网站有这条线

    window.parent.postMessage("Hello From IFrame", "*");
    

    要么

    window.parent.postMessage("Hello From IFrame", "http://foo.com");
    

    然后siteA有以下代码

    // Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers.
    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
    var eventer = window[eventMethod];
    
    
    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
    
    // Listen to message from child IFrame window
    eventer(messageEvent, function (e) {
       alert(e.data);
       // Do whatever you want to do with the data got from IFrame in Parent form.
    }, false);
    

    如果要添加安全连接,可以在 eventer(messageEvent, function (e) {}) 中使用此条件

    if (e.origin == 'http://iframe.example.com') {
        alert(e.data); 
        // Do whatever you want to do with the data got from IFrame in Parent form.
    }
    

    For IE

    内部IFrame:

    window.parent.postMessage('{"key":"value"}','*');
    

    外:

    eventer(messageEvent, function (e) {
       var data = jQuery.parseJSON(e.data);
       doSomething(data.key);
     }, false);
    

相关问题