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

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

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

我尝试了CSS的margin, padding属性在DIV上成功地占据了网页的整个剩余高度,但这个技巧在iframe上不起作用。

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

668721 次浏览

2019年更新

今天最好的选择是- flexbox。多年来,所有东西都很好地支持它。去吧,不要回头。下面是一个flexbox的代码示例:

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.row-container {display: flex; width: 100%; height: 100%; flex-direction: column; background-color: blue; overflow: hidden;}
.first-row {background-color: lime; }
.second-row { flex-grow: 1; border: none; margin: 0; padding: 0; }
<div class="row-container">
<div class="first-row">
<p>Some text</p>
<p>And some more text</p>
</div>
<iframe src="https://jsfiddle.net/about" class="second-row"></iframe>
</div>

这个答案的其余部分留待学习。历史原因。


关键是要明白这100%是什么。阅读CSS规范可以帮助你。

长话短说——有一种东西叫做“包含块”。-它不一定是父元素。简单地说,它是层次结构中具有position:relative或position:absolute的第一个元素。或者体元素本身,如果没有其他的话。因此,当你输入“width: 100%”时,它会检查包含“block”的宽度。并将元素的宽度设置为相同的大小。如果那里有其他东西,那么你可能会得到一个“包含块”的内容;比自身更大(因此“溢出”)。

身高也有同样的作用。只有一个例外。你不能让高度达到浏览器窗口的100%。最顶层的元素是body(或html?)不确定)元素,并且该元素的延伸足以包含其内容。指定高度:100%将没有效果,因为它没有“父元素”。以此来衡量100%。窗口本身不算数。;)

要使某些内容伸展到窗口的100%,您有两个选择:

  1. 使用JavaScript
  2. 不要使用DOCTYPE。这不是一个很好的做法,但它会使浏览器处于“怪癖模式”,在这种模式下,你可以对元素执行height="100%",它会将它们拉伸到窗口大小。请注意,为了适应DOCTYPE的变化,页面的其余部分可能也必须进行更改。

更新:我不确定当我发布这篇文章时我是否已经错了,但这确实是过时的。现在你可以在样式表:html, body { height: 100% }中这样做,它实际上会延伸到整个视口。即使使用DOCTYPE。min-height: 100%也可能有用,这取决于你的情况。

我也不建议任何人制作怪癖模式的文档了,因为它引起的头痛远远多于解决它们。每种浏览器都有不同的怪癖模式,因此要让页面在不同浏览器之间保持一致就变得困难了两个数量级。使用DOCTYPE。总是这样。最好是HTML5的<!DOCTYPE html>。它很容易记住,并且在所有浏览器中都很有魅力,即使是10年前的浏览器。

唯一的例外是你必须支持IE5之类的东西。如果你在那里,那你就只能靠自己了。那些古老的浏览器与今天的浏览器完全不同,这里给出的一些建议将帮助您使用它们。好的一面是,如果你在那里,你可能只需要支持一种浏览器,这就解决了兼容性问题。

好运!

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

选项1 -绝对定位。当你知道第一部分的精确高度时,很好很干净。

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.first-row {position: absolute;top: 0; left: 0; right: 0; height: 100px; background-color: lime;}
.second-row {position: absolute; top: 100px; left: 0; right: 0; bottom: 0; background-color: red }
.second-row iframe {display: block; width: 100%; height: 100%; border: none;}
<div class="first-row">
<p>Some text</p>
<p>And some more text</p>
</div>
<div class="second-row">
<iframe src="https://jsfiddle.net/about"></iframe>
</div>

注意:second-row容器是需要的,因为由于某些原因,bottom: 0right: 0在iframe上不起作用。与被“取代”有关;元素。但是width: 100%height: 100%工作得很好。display: block是必需的,因为它默认是inline元素,否则空格会产生奇怪的溢出。

选项2表。当你不知道第一部分的高度时,它是有效的。你可以使用实际的<table>标记,也可以用奇特的方式使用display: table。我选择后者,因为这似乎是最近的时尚。

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.row-container {display: table; empty-cells: show; border-collapse: collapse; width: 100%; height: 100%;}
.first-row {display: table-row; overflow: auto; background-color: lime;}
.second-row {display: table-row; height: 100%; background-color: red; overflow: hidden }
.second-row iframe {width: 100%; height: 100%; border: none; margin: 0; padding: 0; display: block;}
<div class="row-container">
<div class="first-row">
<p>Some text</p>
<p>And some more text</p>
</div>
<div class="second-row">
<iframe src="https://jsfiddle.net/about"></iframe>
</div>
</div>

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

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

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.row-container {display: flex; width: 100%; height: 100%; flex-direction: column; background-color: blue; overflow: hidden;}
.first-row {background-color: lime; }
.second-row { flex-grow: 1; border: none; margin: 0; padding: 0; }
<div class="row-container">
<div class="first-row">
<p>Some text</p>
<p>And some more text</p>
</div>
<iframe src="https://jsfiddle.net/about" class="second-row"></iframe>
</div>

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

没错,你所展示的iframe的高度是它的容器(body)的100%。

试试这个:

<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的高度更改为您想要的高度。

我认为你有一个概念上的问题。说“我试着在iframe上设置高度:100%,结果很接近,但iframe试图填满整个页面”,好吧,什么时候“100%”不等于“整体”?

你已经要求iframe填充它的容器(也就是body)的整个高度,但不幸的是,它在<div>上面你要求的是30px大。所以父容器的总大小现在被要求为100% + 30px > 100%!因此滚动条。

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

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

  1. 绝对定位您的div,其中 会把它从容器里拿出来吗 单独的iframe将消耗它的 容器的高度。这就剩下你 还有各种各样的问题 虽然,但也许是为了你 做不透明或对齐将 李好。< / p > < / >

  2. 或者需要指定a %高度的div和减少 iframe的高度减去那么多。 如果绝对高度是 这很重要,你需要申请 这是div的子元素 李。< / p > < / >

您可以通过在加载/调整大小事件上测量正文大小并将高度设置为(full height - banner height)来实现这一点。

请注意,目前在IE8 Beta2中,您不能执行此onresize操作,因为该事件目前在IE8 Beta2中已中断。

我们使用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的作者)创建。

或者你可以使用老派的框架集:

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

你可以用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>
另一种方法是在父节点上使用position: fixed; 如果我没有弄错的话,position: fixed;将元素绑定到viewport,因此,一旦你赋予这个节点width: 100%;height: 100%;属性,它将横跨整个屏幕。从这一点开始,你可以把<iframe>标签放在它里面,并通过简单的width: 100%; height: 100%; CSS指令跨越剩余的空间(包括宽度和高度)

示例代码


    body {
margin: 0px;
padding: 0px;
}


/* iframe's parent node */
div#root {
position: fixed;
width: 100%;
height: 100%;
}


/* iframe itself */
div#root > iframe {
display: block;
width: 100%;
height: 100%;
border: none;
}
   <html>
<head>
<title>iframe Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="root">
<iframe src="http://stackoverflow.com/">
Your browser does not support inline frames.
</iframe>
</div>
</body>
</html>

也许这个问题已经有了答案(上面的一些答案是“正确的”方法),但我想我只是补充我的解决方案。

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

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

当然,“#middle”是div的id。你需要做的唯一额外的事情是,每当用户调整窗口大小时,召回这个大小变化。

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

在尝试了一段时间的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测试

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;

我是这么做的。我也遇到了同样的问题,最后花了几个小时在网上搜索资源。

<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列的表的中间单元格内。

你可以用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>

试试下面的方法:

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

这对我很有效

虽然我同意JS似乎是一个更好的选择,我有一个有点CSS只工作的解决方案。它的缺点是,如果您必须频繁地向iframe html文档添加内容,您将不得不调整一个百分比的时间。

解决方案:

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

html, body, section, main-div {}

然后只编写如下代码:

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

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

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

这是因为它可以防止第二个html文档(一个嵌入)从父html文档继承它的高度。它阻止了它,因为我们没有为它们都指定高度。当我们给子对象一个%时,它会寻找它的父对象,如果没有,它会取它的内容高度。前提是其他容器没有给定高度。

"无缝的"属性是一个旨在解决这个问题的新标准:

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

当分配此属性时,它将删除边框和滚动条,并将iframe大小设置为其内容大小。 虽然它只支持Chrome和最新的Safari

更多关于这个: HTML5 iFrame无缝属性 < / p >

一个简单的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();
}


}

你不能设置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>

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>

以下是一些现代的方法:


  • 方法1 - 视口相对单位 / calc()的组合。

    表达式calc(100vh - 30px)表示剩余的高度。其中100vh是浏览器的高度,而calc()的使用有效地取代了另一个元素的高度。

    示例 .

    .
    body {
    margin: 0;
    }
    .banner {
    background: #f00;
    height: 30px;
    }
    iframe {
    display: block;
    background: #000;
    border: none;
    height: calc(100vh - 30px);
    width: 100%;
    }
    <div class="banner"></div>
    <iframe></iframe>

    支持calc()这里;支持视口相对单位在这里.


  • 进近2 -灵活进近

    示例 .

    将公共父元素的display设置为flex,同时设置为flex-direction: column(假设您希望元素堆叠在彼此之上)。然后在子元素iframe上设置flex-grow: 1,以便它填充剩余的空间。

    .
    body {
    margin: 0;
    }
    .parent {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    }
    .parent .banner {
    background: #f00;
    width: 100%;
    height: 30px;
    }
    .parent iframe {
    background: #000;
    border: none;
    flex-grow: 1;
    }
    <div class="parent">
    <div class="banner"></div>
    <iframe></iframe>
    </div>

    由于这种方法有不支持1,我建议使用前面提到的方法。< / p >

1虽然它似乎在Chrome/FF中工作,但它在IE中不起作用(第一种方法在所有当前的浏览器中都有效)。

它将与下面提到的代码一起工作

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

如果你可以访问将要加载的iframe的内容,你可以告诉它的父元素在它调整大小的时候调整大小。

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

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

类似的答案@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

我认为最好的方法来实现这个场景使用css位置。设置位置相对于你的父div和position:绝对于你的iframe。

.
.container{
width:100%;
position:relative;
height:500px;
}


iframe{
position:absolute;
width:100%;
height:100%;
}
<div class="container">
<iframe src="http://www.w3schools.com">
<p>Your browser does not support iframes.</p>
</iframe>
</div>

对于其他填充和边距问题,现在一个天css3 calc()是非常先进的,大多数兼容所有浏览器以及。

检查钙()

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

为什么不这样做(对body padding/margin进行轻微调整)

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

另一种替代方法使用vh

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