根据内部内容使iframe高度动态-JQUERY / Javascript


202

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

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

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

所在TB_window的div在哪里 Iframe

body -iframe中aspx的body标签。

该脚本已附加到iframe内容中。我TB_window从父页面获取元素。虽然这在Chrome上可以正常运行,但是TB_window在Firefox中崩溃。我真的很困惑/迷茫,为什么会这样。


那.aspx iframe页面是来自同一域名?
AlexC 2012年

您可以检查$(“ body”)。height()在firefox中是否有值?
Michael L Watson

是的.. iframe与容器页面位于同一域中
karry 2012年

@MichaelLWatson看起来萤火虫监视窗口的身高值为0 ...虽然Chrome确实有一个值
karry 2012年

Answers:


211

您可以使用以下方法检索内容的高度IFRAMEcontentWindow.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()" ...

我有一个情况在不久前,我还需要调用iframeLoadedIFRAME后内发生的形式提交自己。您可以通过在IFRAME的内容脚本中执行以下操作来实现:

parent.iframeLoaded();

152
它在跨域上不支持。
Soumya

3
@Soumya跨域与此代码无关。使用命令绕过了一个安全问题。
亚里斯多斯

9
@Soumya寻找X-FRAME-OPTIONS以添加一行作为:Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");response.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos

15
这解决了跨域iframe大小调整问题github.com/davidjbradshaw/iframe-resizer
David Bradshaw

2
@deebs您也可以尝试更改iFrameID.height = "";iFrameID.height = "20px";。浏览器的默认iframe高度为150px,这是将其""重置为默认高度。
philfreo

112

对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);

6
如果框架中的内容总是在变化,您将怎么办?
凯文(Kevin)

如果内容大小不断变化和/或如果您的iframe设计为位于除iframe提取页面的域之外的其他域上,则您需要做一些不同的事情。
BlueFish

4
为此,解决方案是使用postMessage和receiveMessage。我使用github.com/jeffomatic/nojquery-postmessage
BlueFish 2013年

这个想法是计算新的高度并将消息发送到父框架,该父框架需要接收消息并相应地调整iframe的高度。
BlueFish

对于我而言,它总是有些像素不足,所以我function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
想到了

56

我发现接受的答案是不够的,因为Safari或chrome不支持 X-FRAME-OPTIONS:Allow-From 。取而代之的是采用不同的方法,该数据来自Disqus的Ben Vinegar 的演讲。想法是将事件侦听器添加到父窗口,然后在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中,将一个onLoad添加到body标签以触发调整大小功能:

<body onLoad="resize();">

1
为了使它对我有用,我必须将“ window.parent”更改为“ parent”。
prograhammer

大!但只加载一次高度。如果您想让iframe真正响应,我更喜欢每秒调用一次resize方法,如下所示:setInterval(resize, 1000);
Jules Colle

12

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

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

如果您使用jQuery,请尝试以下代码:

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

6

您可以查看四种不同的属性来获取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

@ djack109最有可能是CSS中的某些内容阻止了页面上的元素缩小
David Bradshaw

3

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

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

2

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

<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>

这里1vh =浏览器窗口高度的1%。因此,要设置的高度的理论值为100vh,但实际上98vh发挥了作用。


9
这没有考虑iframe的内容高度。
阿德里安·保利

当您没有解决跨域戏剧的简单方法时,此距离就足够接近了
dsghi

2

以防万一这对任何人都有帮助。我正在拔头发以使其正常工作,然后我注意到iframe的班级身高为100%。当我删除它时,一切都按预期工作。因此,请检查任何CSS冲突。


2

您还可以在resizeIframe中添加一个重复的requestAnimationFrame(例如,来自@BlueFish的答案),该请求总是在浏览器绘制布局之前被调用,并且可以在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)" ...

您的回调应该足够快,不会对您的整体效果产生重大影响


1
从最初的测试来看,这是一个非常出色的解决方案,效果很好。我会对使用此功能带来的性能影响感兴趣。
KFE

恰好碰到了的情况下Uncaught TypeError: Cannot read property 'scrollHeight' of null,因为bodynull,但是它通常工作。
引发


1

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

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

0

我发现Troy的答案无效。这是为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' );
    }
});

0

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

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

0

当您需要没有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%;
}

0

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

在这种情况下,尺寸为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%;   
}

0

对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上下通过整个屏幕的填充。


0
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);
});

0

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

0

只需将iframe容器位置设为:绝对,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>

-1
$(document).height() // - $('body').offset().top

和/或

$(window).height()

请参阅堆栈溢出问题,如何获得身体元素的高度

尝试使用以下方法在jQuery中查找身体的高度:

if $("body").height()

如果Firebug,则没有值。也许这就是问题所在。


我尝试两者都做...在Firefox上仍然会发生。Firefox以某种方式无法在iframe上获取window.height()。正如我提到的,脚本已附加到iframe内容上,我在document.ready()函数中对其进行了调用
karry 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.