根据内容高度调整iframe高度

69

我正在我的网站上打开我的博客页面。问题是,我可以给一个iframe设置宽度,但高度应该是动态的,这样在iframe中就没有滚动条,看起来像一个单独的页面...

我尝试了各种JavaScript代码来计算内容的高度,但它们都会出现"access denied permission"错误,没有用。

<iframe src="http://bagtheplanet.blogspot.com/" name="ifrm" id="ifrm" width="1024px" ></iframe>

我们能否使用Ajax来计算高度,或者使用PHP?

10个回答

60
直接回答你的两个子问题:不,你不能使用Ajax实现这一点,也不能用PHP来计算它。
我过去所做的是,在嵌入页面中使用 window.onload 触发器(而不是 domready,因为图片加载可能需要一些时间),将页面的body高度传递给父级页面。
<body onload='parent.resizeIframe(document.body.scrollHeight)'>

那么parent.resizeIframe看起来是这样的:

function resizeIframe(newHeight)
{
    document.getElementById('blogIframe').style.height = parseInt(newHeight,10) + 10 + 'px';
}

完成了,现在您拥有一个强大的调整器,它会在页面完全呈现后触发,没有任何恶心的 contentdocumentcontentWindow 的折腾 :)

当然,现在人们将首先看到默认高度的 iframe,但这可以通过一开始隐藏 iframe 并只显示“加载中”图像来轻松处理。然后,当 resizeIframe 函数启动时,在其中加入两行额外的代码,将隐藏加载图像,显示 iframe,实现类似 Ajax 的效果。

当然,这仅适用于相同域名下的情况,因此您可能需要一个代理 PHP 脚本来嵌入这些内容,一旦这样做,您也可以使用 PHP 直接将博客的 RSS 源直接嵌入您的网站中。


我正在使用iframe来加载页面。我的iframe位于主页面中,一旦加载就不会重新加载。只有在主页面上点击链接并将其指向iframe时,iframe中的页面才会更改。在这种情况下,我该如何调整iframe的高度? - this. __curious_geek
@SchizoDuckie 很好的回答,简短明了。 - Danish Iqbal
1
@SchizoDuckie 我遇到了一个问题,iframe和body的大小只增不减,有什么解决办法吗? - Danish Iqbal
我发现第一次加载父屏幕时,它不会重新调整大小。子屏幕需要一些时间来加载。我也发现同样缺乏减小的情况。 - baash05
在Chrome中运行良好,但似乎在IE10中无法正常工作。仍在使用它。谁还使用IE呢? :) - The Muffin Man
显示剩余2条评论

8
你可以使用JavaScript完成这个任务。
document.getElementById('foo').height = document.getElementById('foo').contentWindow.document.body.scrollHeight + "px";

这个脚本让我感到困惑。我想用一个真实的网站来练习:mathsearchun.blogspot.com/。 "id" 是最内层的 div "HTML3" 还是最外层的 div "outer-wrapper"?在 Firebug 中,我得到了诸如“contentWindow 未定义”和“document.getElementById("id") 为空”的错误。它们是什么意思? - Léo Léopold Hertz 준영
你想获取的元素是iframe,我猜在你的情况下是亚马逊。"contentWindow未定义"可能意味着你抓取的元素没有该属性/元素。你需要使用document.getElementById("amazon")来获取你的iframe。 - Anders S
1
这在Chrome和IE中有效,但在Firefox中无效,你能否改进一下以包括Firefox? - Serj Sagan

4

调整IFRAME内容大小是一件相对简单的事情,可以在Google上找到很多相关信息。这里有一个解决方案

<script type="text/javascript">
    function autoIframe(frameId) {
       try {
          frame = document.getElementById(frameId);
          innerDoc = (frame.contentDocument) ? frame.contentDocument : frame.contentWindow.document;
          objToResize = (frame.style) ? frame.style : frame;
          objToResize.height = innerDoc.body.scrollHeight + 10;
       }
       catch(err) {
          window.status = err.message;
       }
    }
</script>

当然,这并不能解决您遇到的跨域问题... 如果这些站点在同一位置,设置document.domain可能有所帮助。如果您正在iframe随机站点,则我认为没有解决方案。

1
你在高度分配上缺少一个单位,例如'px'。这难道不会导致标准模式下的失败吗? - Crescent Fresh

2

以下是我的解决方案,使用MooTools实现,可在Firefox 3.6、Safari 4.0.4和Internet Explorer 7中运行:

var iframe_container = $('iframe_container_id');
var iframe_style = {
    height: 300,
    width: '100%'
};
if (!Browser.Engine.trident) {
    // IE has hasLayout issues if iframe display is none, so don't use the loading class
    iframe_container.addClass('loading');
    iframe_style.display = 'none';
}
this.iframe = new IFrame({
    frameBorder: 0,
    src: "http://www.youriframeurl.com/",
    styles: iframe_style,
    events: {
        'load': function() {
            var innerDoc = (this.contentDocument) ? this.contentDocument : this.contentWindow.document;
            var h = this.measure(function(){
                return innerDoc.body.scrollHeight;
            });            
            this.setStyles({
                height: h.toInt(),
                display: 'block'
            });
            if (!Browser.Engine.trident) {
                iframe_container.removeClass('loading');
            }
        }
    }
}).inject(iframe_container);

将“loading”类样式设置为在iframe容器中间显示Ajax加载图形。然后对于除Internet Explorer之外的浏览器,在其内容加载完成后,它将显示完整高度的IFRAME并删除加载图形。


0

试试这个,你可以随时更改。这个例子使用jQuery。

$('#iframe').live('mousemove', function (event) {   
    var theFrame = $(this, parent.document.body);
    this.height($(document.body).height() - 350);           
});

0
以下是我的onload事件处理程序。
我在jQuery UI对话框中使用了一个IFRAME。不同的用法需要一些调整。 这似乎对我来说(目前)在Internet Explorer 8和Firefox 3.5中起作用。 它可能需要一些额外的微调,但是基本思路应该很清楚。
    function onLoadDialog(frame) {
    try {
        var body = frame.contentDocument.body;
        var $body = $(body);
        var $frame = $(frame);
        var contentDiv = frame.parentNode;
        var $contentDiv = $(contentDiv);

        var savedShow = $contentDiv.dialog('option', 'show');
        var position = $contentDiv.dialog('option', 'position');
        // disable show effect to enable re-positioning (UI bug?)
        $contentDiv.dialog('option', 'show', null);
        // show dialog, otherwise sizing won't work
        $contentDiv.dialog('open');

        // Maximize frame width in order to determine minimal scrollHeight
        $frame.css('width', $contentDiv.dialog('option', 'maxWidth') -
                contentDiv.offsetWidth + frame.offsetWidth);

        var minScrollHeight = body.scrollHeight;
        var maxWidth = body.offsetWidth;
        var minWidth = 0;
        // decrease frame width until scrollHeight starts to grow (wrapping)
        while (Math.abs(maxWidth - minWidth) > 10) {
            var width = minWidth + Math.ceil((maxWidth - minWidth) / 2);
            $body.css('width', width);
            if (body.scrollHeight > minScrollHeight) {
                minWidth = width;
            } else {
                maxWidth = width;
            }
        }
        $frame.css('width', maxWidth);
        // use maximum height to avoid vertical scrollbar (if possible)
        var maxHeight = $contentDiv.dialog('option', 'maxHeight')
        $frame.css('height', maxHeight);
        $body.css('width', '');
        // correct for vertical scrollbar (if necessary)
        while (body.clientWidth < maxWidth) {
            $frame.css('width', maxWidth + (maxWidth - body.clientWidth));
        }

        var minScrollWidth = body.scrollWidth;
        var minHeight = Math.min(minScrollHeight, maxHeight);
        // descrease frame height until scrollWidth decreases (wrapping)
        while (Math.abs(maxHeight - minHeight) > 10) {
            var height = minHeight + Math.ceil((maxHeight - minHeight) / 2);
            $body.css('height', height);
            if (body.scrollWidth < minScrollWidth) {
                minHeight = height;
            } else {
                maxHeight = height;
            }
        }
        $frame.css('height', maxHeight);
        $body.css('height', '');

        // reset widths to 'auto' where possible
        $contentDiv.css('width', 'auto');
        $contentDiv.css('height', 'auto');
        $contentDiv.dialog('option', 'width', 'auto');

        // re-position the dialog
        $contentDiv.dialog('option', 'position', position);

        // hide dialog
        $contentDiv.dialog('close');
        // restore show effect
        $contentDiv.dialog('option', 'show', savedShow);
        // open using show effect
        $contentDiv.dialog('open');
        // remove show effect for consecutive requests
        $contentDiv.dialog('option', 'show', null);

        return;
    }

    //An error is raised if the IFrame domain != its container's domain
    catch (e) {
        window.status = 'Error: ' + e.number + '; ' + e.description;
        alert('Error: ' + e.number + '; ' + e.description);
    }
};

0
关键是从外部脚本获取所有必要的iframe事件。例如,您有一个使用document.createElement创建iFrame的脚本;在同一脚本中,您暂时可以访问iFrame的内容。
var dFrame = document.createElement("iframe");
dFrame.src = "http://www.example.com";
// Acquire onload and resize the iframe
dFrame.onload = function()
{
    // Setting the content window's resize function tells us when we've changed the height of the internal document
    // It also only needs to do what onload does, so just have it call onload
    dFrame.contentWindow.onresize = function() { dFrame.onload() };
    dFrame.style.height = dFrame.contentWindow.document.body.scrollHeight + "px";
}
window.onresize = function() {
    dFrame.onload();
}

这个方法能够成功是因为dFrame在这些函数内部保持了作用域,使得你能够在frame的作用域内访问外部的iFrame元素,从而可以获取实际文档的高度并根据需要进行扩展。这个例子只适用于Firefox,其他浏览器不支持;我可以给你一些变通的方法,但剩下的你自己来解决吧 ;)

响应触发器过于敏感。Scott使用了类似的脚本,但是包含contentWindow.onresize可以在iframe内容更改时调整iframe大小。这对于流体宽度的iframe也非常有用。 - Soup d'Campbells
这个脚本中的 fobj 是指什么? - akaihola
我认为这是一种转录错误。 我复制了一些代码,忘记在一个上下文中交换fobj; 应该是dFrame。 已在答案中修复。 - Soup d'Campbells

0

@SchizoDuckie的答案非常优雅且轻量级,但由于Webkit缺乏scrollHeight的实现(请参见此处),因此在基于Webkit的浏览器(Safari、Chrome、各种移动平台)上无法正常工作。

为了使这个基本想法在Webkit以及Gecko和Trident浏览器上工作,只需要替换

<body onload='parent.resizeIframe(document.body.scrollHeight)'>

使用

<body onload='parent.resizeIframe(document.body.offsetHeight)'>

只要所有的东西都在同一个域名下,这个功能就会非常好用。

根据 http://www.quirksmode.org/dom/w3c_cssom.html 的说明和快速测试,scrollHeight 可以在 Safari 和 Chrome(OS X)上使用。在我的测试中,OffsetHeight 在这两个浏览器中都不能正确工作。 - user462982

0

我刚刚花了三天的时间来解决这个问题。我正在开发一个应用程序,它可以将其他应用程序加载到自己中,并保持固定的页眉和页脚。以下是我想出的解决方案。(我也使用了EasyXDM,并且成功地使用了它,但后来将其删除以使用此解决方案。)

请确保在DOM中存在<iframe>之后运行此代码。将其放入拉取iframe(父级)的页面中。

// get the iframe
var theFrame = $("#myIframe");
// set its height to the height of the window minus the combined height of fixed header and footer
theFrame.height(Number($(window).height()) - 80);

function resizeIframe() {
    theFrame.height(Number($(window).height()) - 80);
}

// setup a resize method to fire off resizeIframe.
// use timeout to filter out unnecessary firing.
var TO = false;
$(window).resize(function() {
    if (TO !== false) clearTimeout(TO);
    TO = setTimeout(resizeIframe, 500); //500 is time in miliseconds
});

-3

尝试在iframe标签上使用scrolling=no属性。Mozilla还有一个overflow-xoverflow-y CSS属性,您可以了解一下。

关于高度,您也可以尝试在iframe标签上使用height=100%


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接