如何使iframe根据其内容自适应高度

25

我看到很多人问如何使iframe高度100%。这可以通过一些CSS轻松实现。它将使iframe相对于设备屏幕显示100%。但是如何根据内容使iframe的高度达到100%?

这是我当前用于根据设备屏幕使iframe高度为100%的代码:

        iframe {
        display: block;
        background: #000;
        border: none;
        height: 100vh;
        width: 100vw;
    }
    <iframe src="https://...">Your Browser Does Not Support iframes!</iframe>

allowfullscreenposition:absolute并没有帮助,除了导致网站模板崩溃。这是我能做的最好的,而不会破坏主要的CSS。请帮忙...

编辑:使用<meta name="viewport" content="width=device-width,initial-scale=1">使iframe内容响应式,因此使用JavaScript预设高度也没有起作用。也许有一种方法可以使用高度单位吗?例如em, ex, rem等?或者将其设置为特定百分比的vw


这在我最新版本的Chrome浏览器中确实有效。你用的是什么浏览器? - Jonathan Chaplin
我正在使用Chrome和Safari。 - Anthony Kung
4个回答

29

我想分享我的解决方案和兴奋心情。我经过四整天的密集研究和失败,但我认为我已经找到了一种使iframes完全响应的巧妙方式!耶!

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

我试过使用MutationObservers,仍然需要几个EventListeners(resize、click等)来确保每次布局变化都能得到正确处理。-如果一个脚本切换元素的可见性会怎样?或者它动态地按需预加载更多内容呢?-另一个问题是从某个地方获取iframe内容的准确高度。大多数人建议使用scrollHeight或offsetHeight,或者通过使用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)中获取预先计算好的宽度和高度的样式值,该方法总是返回该元素的像素完美大小!完美无缺!
注意,此解决方案不适用于跨源(没有任何其他解决方案可以在没有IFrameResizer等双向通信策略的情况下访问iframe DOM)。如果iframe不属于你,JavaScript无法访问它的DOM。
我能想到的仅有的其他跨源解决方案是使用代理,例如https://github.com/gnuns/allorigins。但这将涉及每次请求的深复制 - 换句话说 - 你“窃取”整个页面源代码(使其成为你的并让JavaScript访问DOM)并修补该源中的每个链接/路径,以便它也经过代理。重新链接程序很困难,但可行。
我可能会尝试解决这个跨源问题,但那是另一天的事情了。享受代码吧! :)

如何去除左侧溢出的问题?我看到你已经添加了overflow:hidden的CSS属性,但仍然显示禁用了溢出。 - Fernando Torres
也许是因为我的 iFrame 包含了一个 Google Web 应用程序,但我仍然觉得有必要在我的 CSS 中指定高度。 - Atiq Zabinski
这个几乎完美地工作。有没有办法让它在浏览器调整大小时也能工作? - caffeinehigh
iframe-resizer库使用所有这些方法和其他一些技术来保持iframe的大小始终与其内容一致。 - undefined

13

没有 CSS 的方法可以根据其内容设置 iframe 的高度。您需要使用 JavaScript 获取 iframe 的内容高度,然后将其设置为 iframe 的高度。

如何使用 JavaScript 实现这一点并进行了详细解释,请参考以下问题:

  1. 如何使 iframe 根据内容自动调整高度而不使用滚动条?
  2. 基于 jQuery/Javascript 使 iframe 高度随内容动态变化

  3. 使用 jQuery 调整 iframe 大小以适应内容

  4. 调整 iframe 的宽度和高度以适应其中的内容

  5. 跨域 iframe 调整大小?


感谢您的回复。我已经设置了iframe内容的高度,因为我制作了这个内容,但它是一个响应式的iframe,这意味着高度会随着宽度的变化而变化。所以在Mac上,它将是100%响应式的,但在PC和移动设备上,它将更短。不幸的是,这5种JavaScript方法都没有起作用。 - Anthony Kung
@AnthonyKung 你需要将设置高度的函数绑定到onload和onresize事件上。这样它也会在调整大小时激活。不过你可能需要使用某种形式的节流。 - Tiagojdferreira

5
尝试将position设置为fixed,像这样:
height: 100%;
width: 100%;
position:fixed;

或者像这样:
height: 100vh;
width: 100vw;
position:fixed;

5
请尝试至少用一句话来解释你的答案。 - nicolallias
根据浏览器内容,将高度和宽度固定为100%。 - Web Designer
1
我的意思是,在回答中解释一下。并阅读https://stackoverflow.com/help/how-to-answer。 - nicolallias
感谢回答,但不幸的是它没有起作用。我之前已经尝试过这个方法,因为其他帖子建议过。这会使页脚部分漂浮在iframe的中间。 - Anthony Kung
我在IE11中没有问题,但在Chrome中出现了类似的问题。对于Chrome,我发现"position:absolute"比"position:fixed"更好 - 现在它随着页面滚动,正如我所需的那样,而不是像Anthony Kung描述的那样漂浮。然而,IFrame现在重叠在其下面的部分:( 但是,感觉离解决问题更近了一步。 - Zeek2

-4

将您的 iframe 分配给自定义 ID,然后您就可以将其设置为 vw 或 vh。

#myiframe {
    width:77vw;
    height:calc(77vw / 3);
}
<div align="center"><iframe id="myiframe" src="https://g1.ipcamlive.com/player/player.php?alias=64512bbc49030&skin=white&autoplay=1&disableautofullscreen=1&disablevideofit=1" width="900px" height="300px" frameborder="0" allowfullscreen> </iframe></div>


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