我正在开发一个类似igoogle的应用程序。来自其他应用程序(在其他域中)的内容使用iframe显示。

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

我试图破译的javascript谷歌使用,但它是模糊的,搜索网络至今一无所获。

更新:请注意,内容是从其他域加载的,因此适用同源策略。


当前回答

使用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>

其他回答

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…我为我工作过。

仅供参考:如果你已经在你的iFrame上有一个“height”属性,这只是添加了style="height: xxx"。这可能不是你想要的。

这是一个老话题,但在2020年,这仍然是一个相关的问题。事实上,我已经在另一个旧线程上发布了这个答案^^ (https://stackoverflow.com/a/64110252/4383587)


只是想分享我的解决方案和兴奋之情。我花了整整四天的时间进行密集的研究和失败,但我认为我已经找到了一种让iframe完全响应的巧妙方法!容量!

我尝试了很多不同的方法……我不希望像使用postMessage那样使用双向通信隧道,因为它对于同源来说很尴尬,对于跨源来说很复杂(因为没有管理员愿意打开门并代表您实现它)。

I've tried using MutationObservers and still needed several EventListeners (resize, click,..) to ensure that every change of the layout was handled correctly. - What if a script toggles the visibility of an element? Or what if it dynamically preloads more content on demand? - Another issue was getting an accurate height of the iframe contents from somewhere. Most people suggest using scrollHeight or offsetHeight, or combination of it by using Math.max. The problem is, that these values don't get updated until the iframe element changes its dimensions. To achieve that you could simply reset the iframe.height = 0 before grabbing the scrollHeight, but there are even more caveats to this. So, screw this.

然后,我有了另一个想法,用requestAnimationFrame实验来摆脱我的事件和观察者地狱。现在,我可以立即对每个布局变化做出反应,但我仍然没有可靠的来源来推断iframe的内容高度。然后我偶然发现了getComputedStyle !这是一种启蒙!一切都很顺利。

好吧,看看我从无数次尝试中提炼出来的代码。

function fit() {
    var iframes = document.querySelectorAll("iframe.gh-fit")

    for(var id = 0; id < iframes.length; id++) {
        var win = iframes[id].contentWindow
        var doc = win.document
        var html = doc.documentElement
        var body = doc.body
        var ifrm = iframes[id] // or win.frameElement

        if(body) {
            body.style.overflowX = "scroll" // scrollbar-jitter fix
            body.style.overflowY = "hidden"
        }
        if(html) {
            html.style.overflowX = "scroll" // scrollbar-jitter fix
            html.style.overflowY = "hidden"
            var style = win.getComputedStyle(html)
            ifrm.width = parseInt(style.getPropertyValue("width")) // round value
            ifrm.height = parseInt(style.getPropertyValue("height"))
        }
    }

    requestAnimationFrame(fit)
}

addEventListener("load", requestAnimationFrame.bind(this, fit))

就是这样,没错!在你的HTML代码中写入<iframe src="page.html" class="gh-fit gh-fullwidth"></iframe>。gh-fit只是一个伪CSS类,用于识别DOM中的哪些iframe元素应该受到脚本的影响。gh-fullwidth是一个简单的CSS类,只有一个规则宽度:100%;

上面的脚本自动从DOM中获取所有分配了.gh-fit类的iframe。然后它从document.getComputedStyle(iframe)中获取并使用预先计算的宽度和高度的样式值,其中总是包含该元素的像素完美大小!!只是完美!

注意,此解决方案不能跨起源工作(没有像IFrameResizer这样的双向通信策略,任何其他解决方案也不能)。JS不能访问iframe的DOM,如果它不属于你的话。

我能想到的另一个跨起源解决方案是使用https://github.com/gnuns/allorigins这样的代理。但这将涉及到深度复制你所发出的每个请求——换句话说——你“窃取”了整个页面源代码(让它成为你的,让JS访问DOM),你修补这个源代码中的每个链接/路径,这样它也会通过代理。重新链接程序是一个困难的,但可行的。

我可能会自己尝试解决这个跨起源问题,但那是另一天的事了。享受代码吧!:)

iGoogle小工具必须主动实现调整大小,所以我猜在跨域模型中,如果没有远程内容以某种方式参与,你就无法做到这一点。如果您的内容可以使用典型的跨域通信技术将具有新大小的消息发送到容器页面,那么其余部分就很简单了。

可能有点晚了,因为所有其他的答案都是老的:-)但是…这是我的解决方案。在实际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
        });
    });
});

希望这对大家有所帮助。

这个答案只适用于使用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