我正在开发一个类似igoogle的应用程序。来自其他应用程序(在其他域中)的内容使用iframe显示。
我如何调整iframes的大小以适应iframes的内容的高度?
我试图破译的javascript谷歌使用,但它是模糊的,搜索网络至今一无所获。
更新:请注意,内容是从其他域加载的,因此适用同源策略。
我正在开发一个类似igoogle的应用程序。来自其他应用程序(在其他域中)的内容使用iframe显示。
我如何调整iframes的大小以适应iframes的内容的高度?
我试图破译的javascript谷歌使用,但它是模糊的,搜索网络至今一无所获。
更新:请注意,内容是从其他域加载的,因此适用同源策略。
当前回答
这是一个老话题,但在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),你修补这个源代码中的每个链接/路径,这样它也会通过代理。重新链接程序是一个困难的,但可行的。
我可能会自己尝试解决这个跨起源问题,但那是另一天的事了。享受代码吧!:)
其他回答
https://getbootstrap.com/docs/4.0/utilities/embed/
经过大量的研究,我明白了,这不是一个独特的问题,我打赌Bootstrap处理它。你瞧……
当你想缩小网页以适应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>
可能有点晚了,因为所有其他的答案都是老的:-)但是…这是我的解决方案。在实际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
});
});
});
希望这对大家有所帮助。
下面是一个简单的解决方案,使用与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呈现内容的尺寸。
使用jQuery的最简单方法:
$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
$(this).css("height", $(this).contents().height() + "px");
});