ChatGPT解决这个技术问题 Extra ChatGPT

使 iframe 适合容器剩余高度的 100%

我想设计一个带有横幅和 iframe 的网页。我希望 iframe 可以填充所有剩余的页面高度并在浏览器调整大小时自动调整大小。是否可以在不编写 JavaScript 代码的情况下仅使用 CSS 来完成它?

我尝试在 iframe 上设置 height:100%,结果非常接近,但 iframe 试图填充整个页面高度,包括横幅 div 元素的 30px 高度,所以我得到了不必要的垂直滚动条。这并不完美。

我尝试了 DIV 上的 CSS 边距、填充属性以成功占据网页的整个剩余高度,但该技巧在 iframe 上不起作用。

横幅


R
Ronen Rabinovici

2019年更新

TL;DR:今天最好的选择是——flexbox。一切都很好地支持它并且多年来一直如此。去吧,不要回头。这是 flexbox 的代码示例:

正文,html {宽度:100%;高度:100%;边距:0;填充:0} .row-container {display: flex;宽度:100%;高度:100%;弹性方向:列;背景颜色:蓝色;溢出:隐藏;} .first-row {背景颜色:石灰; } .second-row { 弹性增长:1;边框:无;边距:0;填充:0; }

一些文本

还有一些文本

这个答案的其余部分是出于学习和历史原因而留下的。

诀窍是了解 100% 的内容。阅读 CSS 规范可以帮助你。

长话短说 - 有“包含块”这样的东西 - 这不是父元素所必需的。简单地说,它是层次结构中具有位置:相对或位置:绝对的第一个元素。或者身体元素本身,如果没有别的东西的话。因此,当您说“宽度:100%”时,它会检查“包含块”的宽度并将元素的宽度设置为相同的大小。如果那里还有其他东西,那么您可能会得到比自身大的“包含块”的内容(因此“溢出”)。

高度的工作方式相同。除了一个例外。您无法将高度设置为浏览器窗口的 100%。可以计算 100% 的最顶层元素是 body(或 html?不确定)元素,它的伸展刚好足以包含其内容。在它上面指定 height:100% 不会有任何效果,因为它没有“父元素”来衡量 100%。窗口本身不算数。 ;)

要使窗口完全伸展 100%,您有两个选择: 使用 JavaScript 不使用 DOCTYPE。这不是一个好的做法,但它会将浏览器置于“怪癖模式”,您可以在其中对元素执行 height="100%" 并将它们拉伸到窗口大小。请注意,您页面的其余部分可能也必须更改以适应 DOCTYPE 更改。

更新:我不确定我在发布此内容时是否已经错了,但现在肯定已经过时了。今天,您可以在样式表中执行此操作:html, body { height: 100% },它实际上会延伸到您的整个视口。即使使用 DOCTYPE。 min-height: 100% 也可能有用,具体取决于您的情况。

而且我也不会再建议任何人制作 quirks-mode 文档,因为它带来的麻烦远比解决问题的多。每个浏览器都有不同的 quirks-mode,因此让您的页面在浏览器中保持一致的外观变得更加困难两个数量级。使用文档类型。总是。最好是 HTML5 之一 - <!DOCTYPE html>。它很容易记住,并且在所有浏览器中都具有魅力,即使是 10 年前的浏览器。

唯一的例外是当您必须支持诸如 IE5 之类的东西时。如果你在那里,那么无论如何你都是一个人。那些古老的浏览器与今天的浏览器完全不同,这里给出的一些建议将对您有所帮助。从好的方面来说,如果你在那里,你可能只需要支持一种浏览器,这就消除了兼容性问题。

祝你好运!

更新2:嘿,好久不见! 6 年后,新的选择出现了。我刚刚在下面的评论中进行了讨论,这里有更多适用于当今浏览器的技巧。

选项 1 - 绝对定位。当您知道第一部分的精确高度时,它又漂亮又干净。

正文,html {宽度:100%;高度:100%;边距:0;填充:0} .first-row {位置:绝对;顶部:0;左:0;右:0;高度:100px;背景颜色:石灰;} .second-row {位置:绝对;顶部:100 像素;左:0;右:0;底部:0;背景颜色:红色 } .second-row iframe {显示:块;宽度:100%;高度:100%;边框:无;}

一些文字

还有一些文字

< iframe src="https://jsfiddle.net/about">

一些注意事项 - 需要 second-row 容器,因为 bottom: 0right: 0 由于某种原因在 iframe 上不起作用。与成为“替换”元素有关。但是 width: 100%height: 100% 工作得很好。 display: block 是必需的,因为默认情况下它是一个 inline 元素,否则空格会开始创建奇怪的溢出。

选项 2 - 表格。当您不知道第一部分的高度时工作。您可以使用实际的 <table> 标记,也可以使用 display: table 以奇特的方式进行。我会选择后者,因为这些天它似乎很流行。

正文,html {宽度:100%;高度:100%;边距:0;填充:0} .row-container {显示:表;空单元格:显示;边框折叠:折叠;宽度:100%;高度:100%;} .first-row {display: table-row;溢出:自动;背景颜色:石灰;} .second-row {显示:表行;高度:100%;背景颜色:红色;溢出:隐藏 } .second-row iframe {宽度:100%;高度:100%;边框:无;边距:0;填充:0; display: block;}

一些文字

还有一些文字

< div class="second-row">

一些注意事项 - overflow: auto 确保该行始终包含其所有内容。否则浮动元素有时会溢出。第二行的 height: 100% 确保它尽可能地扩展,将第一行压缩到尽可能小。

推荐:选项 3 - flexbox - 其中最干净的一个。

正文,html {宽度:100%;高度:100%;边距:0;填充:0} .row-container {display: flex;宽度:100%;高度:100%;弹性方向:列;背景颜色:蓝色;溢出:隐藏;} .first-row {背景颜色:石灰; } .second-row { 弹性增长:1;边框:无;边距:0;填充:0; }

一些文本

还有一些文本

一些注意事项 - overflow: hidden 是因为即使在这种情况下使用 display: block,iframe 仍会产生某种溢出。它在全屏视图或片段编辑器中不可见,但小预览窗口有一个额外的滚动条。不知道那是什么,iframe 很奇怪。


@sproketboy 好吧,这是 W3C 的建议。它甚至不是最坏的,也不是很长的路要走。
那么我们是把它放在 IFrame 页面的样式表中,还是放在包含 IFrame 的父页面的样式表中呢?
太棒了,谢谢! flexbox 确实是最干净的,但是这些表格也非常好学,而且似乎可以在没有溢出的情况下工作:jsfiddle.net/dmitri14/1uqh3zgx/2
将最新更新移至此答案的顶部可能值得。我必须经历整个事情才能得到最好的答案,flexbox。
@forgivenson - 确实如此。在此答案的开头添加了注释。
F
Flexo

我们使用 JavaScript 来解决这个问题;这是来源。

var buffer = 20; //scroll bar buffer
var iframe = document.getElementById('ifm');

function pageY(elem) {
    return elem.offsetParent ? (elem.offsetTop + pageY(elem.offsetParent)) : elem.offsetTop;
}

function resizeIframe() {
    var height = document.documentElement.clientHeight;
    height -= pageY(document.getElementById('ifm'))+ buffer ;
    height = (height < 0) ? 0 : height;
    document.getElementById('ifm').style.height = height + 'px';
}

// .onload doesn't work with IE8 and older.
if (iframe.attachEvent) {
    iframe.attachEvent("onload", resizeIframe);
} else {
    iframe.onload=resizeIframe;
}

window.onresize = resizeIframe;

注意:ifm 是 iframe ID

pageY() 由 John Resig(jQuery 的作者)创建


J
JIBIN BJ

另一种方法是在父节点上使用 position: fixed;
如果我没记错的话,position: fixed; 会将元素与视口联系起来,因此,一旦你给这个节点 width: 100%;height: 100%; 属性,它将跨越整个屏幕。从此时起,您可以将 <iframe> 标记放入其中,并使用简单的 width: 100%; height: 100%; CSS 指令将其跨越剩余空间(宽度和高度)。

示例代码

身体{边距:0px;填充:0px; } /* iframe 的父节点 */ div#root { position: fixed;宽度:100%;高度:100%; } /* iframe 本身 */ div#root > iframe { display: block;宽度:100%;高度:100%;边框:无; } iframe 测试


这如何占据“剩余”高度..?
我注意到您还需要将 position: fixed 添加到 iframe。
没有可见的滚动条
完美 - 你能解释一下 css '>' 例如 div#root > iframe 因为我不熟悉它并且找不到参考
@andrej 任何启用滚动条的方法
J
Josh Crozier

以下是一些现代方法:

方法 1 - 视口相对单位 / calc() 的组合。表达式 calc(100vh - 30px) 表示剩余高度。其中 100vh 是浏览器的高度,使用 calc() 有效地置换了其他元素的高度。这里的例子 body { margin: 0; } .banner { 背景:#f00;高度:30px; } iframe { 显示:块;背景:#000;边框:无;高度:计算(100vh - 30px);宽度:100%; }

这里支持calc();此处支持视口相关单位。

方法 2 - Flexbox 方法 此处示例 将公共父元素的显示设置为 flex,以及 flex-direction: column(假设您希望元素彼此堆叠)。然后在子 iframe 元素上设置 flex-grow: 1 以填充剩余空间。身体{边距:0; } .parent { 显示:弹性;弹性方向:列;最小高度:100vh; } .parent .banner { 背景:#f00;宽度:100%;高度:30px; } .parent iframe { 背景:#000;边框:无;弹性增长:1; }

由于这种方法支持较少1,我建议采用上述方法。

1虽然在Chrome/FF中似乎可以工作,但在IE中却不行(第一种方法在当前所有浏览器中都可以)。


工作和 IMO 这里提到的两个选项都是最好的方法。我更喜欢 flexbox 选项,因为对于 calc,您需要知道要从 vh 中扣除的空间量。使用 flexbox 只需一个简单的 flex-grow:1 即可。
M
Mohammad Faisal

您可以使用 DOCTYPE,但您必须使用 table。看一下这个:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style>
*{margin:0;padding:0}
html, body {height:100%;width:100%;overflow:hidden}
table {height:100%;width:100%;table-layout:static;border-collapse:collapse}
iframe {height:100%;width:100%}

.header {border-bottom:1px solid #000}
.content {height:100%}
</style>
</head>
<body>
<table>
    <tr><td class="header"><div><h1>Header</h1></div></td></tr>
    <tr><td class="content">
        <iframe src="http://google.com/" frameborder="0"></iframe></td></tr>
</table>
</body>
</html>

至少不需要js!!但它是网络安全的吗?
此解决方案的缺点是 html,body{overflow:hidden;} 将删除页面滚动。
我正在尝试在上面的代码中添加页脚,但页脚没有显示。你能帮忙吗?
T
Tim Geerts

也许这已经得到了回答(上面的一些答案是“正确”的做法),但我想我也应该添加我的解决方案。

我们的 iFrame 加载在一个 div 中,因此我需要其他东西然后是 window.height。看到我们的项目已经严重依赖 jQuery,我发现这是最优雅的解决方案:

$("iframe").height($("#middle").height());

当然,“#middle”是 div 的 id。您需要做的唯一额外的事情是在用户调整窗口大小时调用此大小更改。

$(window).resize(function() {
    $("iframe").height($("#middle").height());
});

a
asimrafi

MichAdel 代码对我有用,但我做了一些小的修改以使其正常工作。

function pageY(elem) {
    return elem.offsetParent ? (elem.offsetTop + pageY(elem.offsetParent)) : elem.offsetTop;
}
var buffer = 10; //scroll bar buffer
function resizeIframe() {
    var height = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
    height -= pageY(document.getElementById('ifm'))+ buffer ;
    height = (height < 0) ? 0 : height;
    document.getElementById('ifm').style.height = height + 'px';
}
window.onresize = resizeIframe;
window.onload = resizeIframe;

D
Danut Milea

这就是我所做的。我遇到了同样的问题,最终在网上搜索了几个小时的资源。

<style type="text/css">
   html, body, div, iframe { margin:0; padding:0; height:100%; }
   iframe { position:fixed; display:block; width:100%; border:none; }
</style>

我将此添加到头部。

请注意,我的 iframe 位于具有 3 行和 1 列的表格的中间单元格内。


您的代码仅适用于包含 IFRAME 的 TD 的高度:100%。如果表格包含在 DIV 元素中,它将起作用,因为您有一个让所有 div 具有高度:100% 的样式。
m
montrealmike

使用 vh 的另一种选择

<iframe src='/' style="display:block; border:none; height:100vh; width:100%;"></iframe>

A
ARemesal

没错,您正在展示一个相对于其容器 100% 高度的 iframe:body。

尝试这个:

<body>
  <div style="width:100%; height:30px; background-color:#cccccc;">Banner</div>
  <div style="width:100%; height:90%; background-color:transparent;">
    <iframe src="http: //www.google.com.tw" style="width:100%; height:100%;">
    </iframe> 
  </div>
</body>

当然,把第二个div的高度改成你想要的高度。


可以使用 calc(100% - 30px) 而不是 90%
v
vdbuilder

您可以使用 html/css 执行此操作,如下所示:

<body>
    <div style="width:100%; height:30px; background-color:#cccccc;">Banner</div>
    <iframe src="http: //www.google.com.tw" style="position:fixed;top:30px;bottom:0px;width:100%;"></iframe>
</body>

s
sree

尝试以下操作:

<iframe name="" src="" width="100%" style="height: 100em"/>

它对我有用


不填充父级,只是在 iframe 上放置一个很大的高度。
S
Stefan Steiger

HTML5 中的新功能:使用 calc(在高度上)

<html style="width:100%; height:100%; margin: 0px; padding: 0px;">
<body style="width:100%; height:100%; margin: 0px; padding: 0px;">
<div style="width:100%; height:30px; background-color:#cccccc;">Banner</div>
<iframe src="http://www.google.com.tw" style="width:100%; height: calc(100% - 30px);"></iframe>
</body>
</html>

d
daamsie

我使用 display:table 来解决类似的问题。它几乎适用于此,留下一个小的垂直滚动条。如果您尝试使用 iframe 以外的其他内容填充该灵活列,则它可以正常工作(不是

采取以下 HTML

<body>
  <div class="outer">
    <div class="banner">Banner</div>
    <div class="iframe-container">
      <iframe src="http: //www.google.com.tw" style="width:100%; height:100%;border:0;"></iframe>
    </div>
  </div>
</body>

将外部 div 更改为使用 display:table 并确保它设置了宽度和高度。

.outer {
  display: table;
  height: 100%;
  width: 100%;
}

将横幅设为表格行并将其高度设置为您的偏好:

.banner {
  display: table-row;
  height: 30px;
  background: #eee;
}

在您的 iframe(或您需要的任何内容)周围添加一个额外的 div 并将其设置为高度设置为 100% 的表格行(如果您想嵌入 iframe 来填充高度,则设置其高度至关重要)

.iframe-container {
  display: table-row;
  height: 100%;
}

下面是一个 jsfiddle 显示它在工作中(没有 iframe,因为这似乎在小提琴中不起作用)

https://jsfiddle.net/yufceynk/1/


D
Diodeus - James MacFarlane

我认为你在这里有一个概念问题。要说“我在 iframe 上尝试 set height:100%,结果很接近但 iframe 试图填满整个页面”,那么,“100%”何时不等于“whole”?

您已要求 iframe 填充其容器(即主体)的整个高度,但不幸的是,它在上面的

中有一个块级兄弟姐妹,您要求其为 30px 大。所以现在要求父容器总数调整为 100% + 30px > 100%!因此滚动条。

我认为你的意思是你希望 iframe 像框架和表格单元格一样消耗剩下的东西,即 height="*"。 IIRC 这不存在。

不幸的是,据我所知,也没有办法有效地混合/计算/减去绝对和相对单位,所以我认为你只能选择两种选择:

绝对定位您的 div,这会将其从容器中取出,因此仅 iframe 将消耗它的容器高度。这会给你留下各种各样的其他问题,但也许你正在做的事情不透明或对齐是可以的。或者,您需要为 div 指定 % 高度,并将 iframe 的高度降低这么多。如果绝对高度真的那么重要,您需要将其应用于 div 的子元素。


b
benb

在尝试了一段时间的 css 路由之后,我最终在 jQuery 中编写了一些相当基本的东西来为我完成这项工作:

function iframeHeight() {
    var newHeight = $j(window).height();
    var buffer = 180;     // space required for any other elements on the page 
    var newIframeHeight = newHeight - buffer;
    $j('iframe').css('height',newIframeHeight);    //this will aply to all iframes on the page, so you may want to make your jquery selector more specific.
}

// When DOM ready
$(function() {
    window.onresize = iframeHeight;
}

在 IE8、Chrome、Firefox 3.6 中测试


m
mgr

它将与下面提到的代码一起使用

<iframe src="http: //www.google.com.tw"style="position: absolute; height: 100%; border: none"></iframe>

R
Roy Shmuli

@MichAdel 的类似答案,但我使用的是 JQuery 并且更优雅。

<script type="text/javascript">
    $(document).ready(function() {
        var $iframe = $('#iframe_id')[0];

        // Calculate the total offset top of given jquery element
        function totalOffsetTop($elem) {
            return $elem.offsetTop + ($elem.offsetParent ? totalOffsetTop($elem.offsetParent) : 0);
        }

        function resizeIframe() {
            var height = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
            height -= totalOffsetTop($iframe);
            $iframe.height = Math.max(0, height) + 'px';
        }

        $iframe.onload = resizeIframe();
        window.onresize = resizeIframe;
    });
</script>

iframe_id 是 iframe 代码的 ID


a
access_granted

为什么不这样做(对主体填充/边距进行微调)

<script>
  var oF = document.getElementById("iframe1");
  oF.style.height = document.body.clientHeight - oF.offsetTop - 0;
</script>

最后,您需要将 -0 替换为 +'px'。它可以在手机上使用吗?
s
scunliffe

您可以通过测量加载/调整大小事件的主体大小并将高度设置为(全高 - 横幅高度)来做到这一点。

请注意,目前在 IE8 Beta2 中,您无法在调整大小时执行此操作,因为该事件目前在 IE8 Beta2 中已被破坏。


A
Amir Arad

或者你可以去老派并使用 frameset 也许:

<frameset rows="30,*">
  <frame src="banner.swf"/>
  <frame src="inner.html" />
</frameset>

@vdbuilder:不,它仅在 html5 之前有效。我敢打赌它仍然有效。 ;-)
p
pixelfe

虽然我同意 JS 似乎是一个更好的选择,但我有一个仅适用于 CSS 的解决方案。它的缺点是,如果您必须经常向 iframe html 文档添加内容,您将不得不调整 1% 的时间。

解决方案:

尝试不为您的 html 文档指定任何高度,

html, body, section, main-div {}

然后只编码:

#main-div {height:100%;}
#iframe {height:300%;}

注意: div 应该是您的主要部分。

这应该相对有效。 iframe 确实计算了可见窗口高度的 300%。如果第二个文档(在 iframe 中)的 html 内容的高度小于浏览器高度的 3 倍,则它可以工作。如果您不需要经常向该文档添加内容,这是一个永久的解决方案,您可以根据您的内容高度找到自己需要的百分比。

这是有效的,因为它可以防止第二个 html 文档(嵌入的那个)从父 html 文档继承其高度。它阻止了它,因为我们没有为它们指定一个高度。当我们给孩子一个 % 时,它会寻找它的父母,如果没有,它会获取它的内容高度。并且只有在其他容器没有被指定高度的情况下,根据我的尝试。


C
Community

“无缝”属性是旨在解决此问题的新标准:

http://www.w3schools.com/tags/att_iframe_seamless.asp

分配此属性时,它将删除边框和滚动条并将 iframe 调整为其内容大小。虽然它仅在 Chrome 和最新的 Safari 中受支持

更多信息在这里:HTML5 iFrame Seamless Attribute


无缝属性已从 HTML 5 规范中删除。
u
unloco

一个简单的jQuery解决方案

在 iframed 页面内的脚本中使用它

$(function(){

    if(window != top){
        var autoIframeHeight = function(){
            var url = location.href;
            $(top.jQuery.find('iframe[src="'+ url +'"]')).css('height', $('body').height()+4);
        }
        $(window).on('resize',autoIframeHeight);
        autoIframeHeight();
    }

}

P
Pravin Abhale

您不能以 % 为单位设置 iframe 高度,因为您的父身高不是 100%,所以将父身高设为 100%,然后应用 iframe 高度 100%

For eg.
<html>
<head>
<style>
html,body{height:100%}
</style> 
</head>
<body>
<iframe src="http://www.quasarinfosystem.com" height="100%" width="100%" ></iframe>
</body>
</html>

S
Stephen

如果您有权访问要加载的 iframe 的内容,则可以告诉其父级在调整大小时调整大小。

    $(window).resize(function() {
        $(parent.document)
            .find("iframe")
            .css("height", $("body").css("height"));        
    }).trigger("resize");

如果页面上有多个 iframe,则可能需要使用 id 或其他巧妙的方法来增强 .find("iframe") 以便选择正确的 iframe。


J
Jay Patel

我认为使用 css 位置实现这种情况的最佳方法。设置相对于您的父 div 的位置和位置:绝对到您的 iframe。

.container{ 宽度:100%;位置:相对;高度:500 像素; } iframe{ 位置:绝对;宽度:100%;高度:100%; }

现在,对于其他填充和边距问题,css3 calc() 非常先进,并且几乎与所有浏览器兼容。

检查calc()