English 中文(简体)
将Iframe设置为适应容器剩余高度的100%。
原标题:
  • 时间:2008-11-28 08:23:48
  •  标签:

我想设计一个带 banner 和 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>
最佳回答

Update in 2019

TL;DR: 今天最好的选项是- 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>

The rest of this answer is left for learning & historical reasons.


诀窍在于了解100%是什么。阅读CSS规范可以帮助你。

长话短说 - 存在所谓的“包含块”,它并不必须是父元素。简单地说,它是在层次结构中具有 position:relative 或 position:absolute 的第一个元素。如果没有其他元素,则是 body 元素本身。因此,当您说“width: 100%”时,它会检查“包含块”的宽度,并将您的元素的宽度设置为相同大小。如果有其他东西存在,则您可能会得到比自身更大的“包含块”内容(因此“溢出”)。

高度的工作方式是相同的。除了一个例外。您无法将高度设置为浏览器窗口的100%。可以计算出100%的最高级元素是body(或html?不确定)元素,并且它只要容纳其内容就足够了。在它上面指定height:100%将没有任何效果,因为它没有“父元素”可以测量100%。窗口本身不计入其中。;)

要让某个东西恰好拉伸到窗口的100%,您有两个选择:

  1. Use JavaScript
  2. Don t use DOCTYPE. This is not a good practice, but it puts the browsers in "quirks mode", in which you can do height="100%" on elements and it will stretch them to the window size. Do note, that the rest of your page will probably have to be changed too to accommodate for the DOCTYPE changes.

更新:我不确定我在发布这篇文章时是否已经出错了,但现在肯定已经过时了。今天,您可以在样式表中执行以下操作:html,body {height:100%},它实际上将扩展到您的整个视口。即使带有 DOCTYPE。根据您的情况,min-height:100% 也可能有用。

我也不会建议任何人制作quirks-mode文档,因为它会带来比解决问题更多的烦恼。每个浏览器都有不同的quirks-mode,因此要让您的页面在浏览器中保持一致,就变得更加困难。始终使用DOCTYPE。最好使用HTML5一个-。它很容易记住,并且在所有浏览器中都可以正常运行,即使是10年前的浏览器也是如此。

唯一的例外是当你必须支持类似 IE5 的东西时。如果你在那里,那么你无论如何都要自己解决。那些古老的浏览器与今天的浏览器完全不同,这里给出的任何建议都不会对它们有帮助。但好的一面是,如果你在那里,你可能只需要支持一种浏览器,这样可以消除兼容性问题。

祝你好运! (Zhù nǐ hǎo yùn!)

更新2: 嘿,已经很长时间了!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在某些情况下不能用于iframes。这与它是“替换”元素有关。但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仍会生成某种溢出。它在全屏视图或片段编辑器中不可见,但是小预览窗口会获得额外的滚动条。不知道那是什么,iframes很奇怪。

问题回答

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

Another way to do that would be to use the position: fixed; on parent node.
If I am not mistaken, position: fixed; ties the element to viewport, thus, once you give this node width: 100%; and height: 100%; properties, it will span over entire screen. From this point on, you can put <iframe> tag inside it and span it over remaining space (both in width and in height) with simple width: 100%; height: 100%; CSS instruction.

示例代码


    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>

Here are a few modern approaches:


  • Approach 1 - Combination of viewport relative units / 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>

    在这里支持< a href="http://caniuse.com/#feat=calc">calc() ;在此处支持< a href="http://caniuse.com/#feat=viewport-units">视窗相关单位。


  • Approach 2 - Flexbox approach

    这里有示例

    将共同的父元素的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,我建议采用前面提到的方法。

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

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

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

我们的 iFrame 是在 div 中加载的,因此我需要的不是 window.height。而且,考虑到我们的项目已经严重依赖于 jQuery,我认为这是最优雅的解决方案:

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

当然,其中“#middle”是div的id。你需要做的唯一额外的事情就是在用户调整窗口大小时重新调整这个大小。

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

没错,您正在显示一个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的高度更改为您想要的高度。

迈克尔的代码对我有效,但我进行了一些小修改才能使其正常工作。

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

另一种选择是使用 vh

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

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

它对我有效。

新 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>

我使用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%;
}

Make the banner a table-row and set its height to whatever your preference is:

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

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

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

以下是一个jsfiddle示例(没有使用iframe,因为在fiddle中似乎无法使用)

将此翻译为中文:https://jsfiddle.net/yufceynk/1/ https://jsfiddle.net/yufceynk/1/

我认为您在这里有一个概念上的问题。说“我尝试在 iframe 上设置 height:100%,结果非常接近,但 iframe 试图填充整个页面”,好吧,100%什么时候不等于全部了呢?

你已經要求 iframe 填滿其容器的整個高度(即 body),但不幸的是,它在上面的

中有一個块級同級元素,你要求其大小為 30 像素。因此,父容器的總大小現在被要求調整為 100% + 30px > 100%!因此出現滾動條。

我认为你的意思是,你希望iframe像框架和表格单元格一样,可以使用“*”来消耗空间。据我所知,这个不存在。

很不幸,据我所知,目前没有有效混合/计算/减去绝对单位和相对单位的方法,因此我认为您只有两个选择:

  1. Absolutely position your div, which will take it out of the container so the iframe alone will consume it s containers height. This leaves you with all manner of other problems though, but perhaps for what you re doing opacity or alignment would be ok.

  2. Alternatively you need to specify a % height for the div and reduce the height of the iframe by that much. If the absolute height is really that important you ll need to apply that to a child element of the div instead.

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

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

<iframe src="http: //www.google.com.tw"style="position: absolute; height: 100%; border: none"></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。"

为什么不这样做(稍微调整一下填充/边距)?

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

你可以通过在载入/调整事件上测量身体尺寸并将高度设置为(全高-横幅高度)来完成此操作。

请注意,目前在IE8 Beta2中,你不能在onresize上执行此操作,因为此事件当前在IE8 Beta2中损坏。

或者您可以使用老式的frameset

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

虽然我同意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)从父 HTML 文档中继承其高度。这是因为我们没有为它们两个指定高度。当我们为子指定一个%时,它会查找其父级,如果没有,则采用其内容高度。从我尝试的情况来看,只有其他容器没有给出高度。

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

将其翻译成中文:http://www.w3schools.com/tags/att_iframe_seamless.asp

When assigning this attribute it will remove borders and scroll bars and size the iframe to its content size. though it is only supported in Chrome and latest Safari

more on this here: HTML5 iFrame Seamless Attribute

一个简单的 jQuery 解决方案

在iframe页面内的脚本中使用这个。

$(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 的高度,因为你的父级 Body 的高度不是 100%。请将父级 Body 的高度设为 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>

如果您可以访问即将加载的iframe的内容,您可以告诉其父级在iframe调整大小时重新调整大小。

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

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

我认为使用css定位是实现此情况的最佳方法。将位置相对于父元素设置为相对位置,将位置设置为绝对位置的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()已经非常先进,并且大多数浏览器都兼容。

检查 calc()





相关问题