根据内容调整iframe的大小

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

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

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

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

337447 次浏览

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

我相信这样的做法会奏效。

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

在iframe内容中加载你的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"。这可能不是你想要的。

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

我们有这种类型的问题,但稍微与您的情况相反-我们正在向其他域的网站提供iframed内容,因此同源策略也是一个问题。在花了好几个小时搜索谷歌后,我们最终找到了一个(有点..)可行的解决方案,您可能能够适应您的需求。

有一种方法可以绕过同源策略,但它需要同时对iframe内容和框架页面进行更改,因此,如果您不能同时请求更改两边的内容,那么这种方法恐怕对您没有多大用处。

有一个浏览器的怪癖,它允许我们绕过同源策略——javascript可以与自己域中的页面通信,也可以与它已经框架的页面通信,但不能与它被框架的页面通信,例如,如果你有:

 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的消息,而也可以交流可以接收来自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

facebook如何处理它的这里有一个解释,这可能比我上面的稍微清楚一点!

人力资源/ > < p > < 代码< / >强

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>

如果你不需要处理来自不同域的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>

下面是一个简单的解决方案,使用与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呈现内容的尺寸。

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

window.postMessage ()

窗口。postMessage是一种安全启用跨源通信的方法。通常,当且仅当执行它们的页面位于具有相同协议(通常都是http)、端口号(80是http的默认值)和主机(对文档取模)的位置时,才允许不同页面上的脚本相互访问。域名被两个页面设置为相同的值)。窗口。postMessage提供了一种受控制的机制来绕过这种限制,这种机制在正确使用时是安全的。

总结

窗口。当调用postMessage时,当任何必须执行的挂起脚本完成时(例如剩余的事件处理程序if窗口),将在目标窗口分派MessageEvent。postMessage从事件处理程序、之前设置的挂起超时等调用)。MessageEvent具有类型message,这是一个数据属性,设置为提供给窗口的第一个参数的字符串值。postMessage,一个原点属性,对应于窗口调用窗口中主文档的原点。postMessage在时间窗口。postMessage被调用,还有一个源属性,即窗口所在的窗口。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

HTML 5工作草案在window.postMessage

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

John Resig谈跨窗口消息传递

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

当你想缩小网页以适应iframe大小时:

  1. 你应该调整iframe的大小以适应内容
  2. 然后你应该缩小整个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>

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

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

我正在实现ConroyP的帧中帧解决方案,以取代基于设置文档的解决方案。域,但发现它是相当困难的确定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

这在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);
}

代码没有优化,这是从我的devel测试:)

希望有人觉得这有用!

使用jQuery的最简单方法:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
$(this).css("height", $(this).contents().height() + "px");
});
这是一个jQuery的方法,通过iframe的src属性在json中添加信息。这是一个演示,调整大小和滚动这个窗口。使用json生成的url如下所示… http://fiddle.jshell.net/zippyskippy/RJN3G/show/ {scrollHeight windowHeight docHeight: 5124: 1019: 571} # < / p >

下面是fiddle 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);
<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>

获取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);
}

可能有点晚了,因为所有其他的答案都是老的:-)但是…这是我的解决方案。在实际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使用window.postMessage(message, targetOrigin);发送数据到父网站。下面我来解释一下我是怎么做到的。

Site A = < A href="http://foo.com" rel="noreferrer">http://foo.com Site B = http://bar.com

sitb在网站内部加载

SiteB网站有这条线

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

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

然后site ea有如下代码

// 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条件

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.
}

对于IE

IFrame内:

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

外:

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

使用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);
}
});

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

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

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


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

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

我已经尝试使用mutationobserver,仍然需要几个eventlistener(调整大小,单击,..),以确保布局的每一个变化都被正确处理。-如果脚本切换元素的可见性怎么办?或者如果它根据需要动态预加载更多内容呢?-另一个问题是从某个地方获得iframe内容的准确高度。大多数人建议使用scrollHeightoffsetHeight,或使用Math.max组合。问题是,直到iframe元素改变其维度,这些值才会更新。要实现这一点,你可以在抓取scrollHeight之前简单地重置iframe.height = 0,但对此还有更多的注意事项。所以,去他的。

然后,我有了另一个想法,用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类,只有一个规则width: 100%;

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

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

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

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

找不到能完美处理大文本+大图像的东西,但我最终得到了这个,似乎这是对的,或者几乎是对的,每一次:

    iframe.addEventListener("load",function(){
// inlineSize, length, perspectiveOrigin, width
let heightMax = 0;
// this seems to work best with images...
heightMax = Math.max(heightMax,iframe.contentWindow.getComputedStyle(iframe.contentWindow.document.body).perspectiveOrigin.split("px")[0]);
// this seems to work best with text...
heightMax = Math.max(heightMax,iframe.contentWindow.document.body.scrollHeight);
// some large 1920x1080 images always gets a little bit off on firefox =/
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if(isFirefox && heightMax >= 900){
// grrr..
heightMax = heightMax + 100;
}


iframe.style.height = heightMax+"px";
//console.log(heightMax);
});


David Bradshaw和Chris Jacob已经建议使用postMessage方法。我完全同意,做这些事情的正确方法。

我只是想发布一个例子,真实的代码,以防它对一些人来说是现成的答案。

在iframed面:

<body onload="docResizePipe()">
<script>
var v = 0;
const docResizeObserver = new ResizeObserver(() => {
docResizePipe();
});
docResizeObserver.observe(document.querySelector("body"));
function docResizePipe() {
v += 1;
if (v > 5) {
return;
}
var w = document.body.scrollWidth;
var h = document.body.scrollHeight;
window.parent.postMessage([w,h], "*");
}
setInterval(function() {
v -= 1;
if (v < 0) {
v = 0;
}
}, 300);
</script>

注意递归阻塞机制——这显然是必要的,因为Firefox中有一个bug,但不管怎样,让它存在吧。

在父文档端:

<iframe id="rpa-frame" src="3.html" style="border: none;"></iframe>
<script>
var rpaFrame = document.getElementById("rpa-frame");


window.addEventListener("message", (event) => {
var width = event.data[0];
var height = event.data[1];
rpaFrame.width = parseInt(width)+60;
rpaFrame.height = parseInt(height)+60;
console.log(event);
}, false);
</script>

希望对大家有用。

我在这里读了很多答案,但几乎每个人都给出了一些交叉起源的框架块。

错误示例:

Uncaught DOMException: Blocked a frame with origin "null"从

.访问跨原点帧

在相关线程中的答案也是一样的:

使iframe自动调整高度根据内容不使用滚动条?< / >

我不想使用第三方库,如iFrame Resizer或类似的库。

来自@ChrisJacob的答案很接近,但我缺少一个完整的工作示例,而不仅仅是链接。@Selvamani和@latitov也是很好的互补。

https://stackoverflow.com/a/3219970/3850405 < a href = " https://stackoverflow.com/a/3219970/3850405 " > < / >

我对iframe使用width="100%",但代码也可以修改为使用width。

这就是我如何解决为iframe设置自定义高度的问题:

嵌入式iframe:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description"
content="Web site" />
<title>Test with embedded iframe</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<iframe id="ifrm" src="https://localhost:44335/package/details?key=123" width="100%"></iframe>
<script type="text/javascript">
window.addEventListener('message', receiveMessage, false);


function receiveMessage(evt) {
console.log("Got message: " + JSON.stringify(evt.data) + " from origin: " + evt.origin);
// Do we trust the sender of this message?
if (evt.origin !== "https://localhost:44335") {
return;
}


if (evt.data.type === "frame-resized") {
document.getElementById("ifrm").style.height = evt.data.value + "px";
}
}
</script>
</body>
</html>

iframe source,来自Create React App的例子,但只使用了HTMLJS

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description"
content="Web site created using create-react-app" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript">
//Don't run unless in an iframe
if (self !== top) {
var rootHeight;
setInterval(function () {
var rootElement = document.getElementById("root");
if (rootElement) {
var currentRootHeight = rootElement.offsetHeight;
//Only send values if height has changed since last time
if (rootHeight !== currentRootHeight) {
//postMessage to set iframe height
window.parent.postMessage({ "type": "frame-resized", "value": currentRootHeight }, '*');
rootHeight = currentRootHeight;
}
}
}
, 1000);
}
</script>
</body>
</html>

带有setInterval的代码当然可以修改,但它对动态内容非常有效。setInterval仅在内容嵌入iframe时激活,而postMessage仅在高度改变时发送消息。

你可以在这里阅读更多关于Window.postMessage()的内容,但是描述非常适合我们想要实现的目标:

window.postMessage()方法安全地启用了跨原点 窗口对象之间的通信;例如,在一页和一页之间 弹出它所衍生的,或者在页面和嵌入的iframe之间 。< / p >

正常情况下,允许不同页面上的脚本相互访问 当且仅当它们来自的页面共享相同的协议时, 端口号和主机(也称为“同源策略”)。 window.postMessage()提供了一种安全的受控机制

.

.

.

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

如果您可以控制iframe内容,我强烈建议使用

ResizeObserver

只需在iframesrcdoc属性的末尾插入以下内容, 逃避如果需要,

<script type="text/javascript">
var ro = new ResizeObserver(entries => {
for (let entry of entries) {
const cr = entry.contentRect;
// console.log(window.frameElement);
window.frameElement.style.height =cr.height +30+ "px";
}
});


ro.observe(document.body);
</script>

https://getbootstrap.com/docs/4.0/utilities/embed/

经过大量的研究,我明白了,这不是一个独特的问题,我打赌Bootstrap处理它。你瞧……