'Make Iframe to fit 100% of container's remaining height
I want to design a web page with a banner and an iframe. I hope the iframe can fill all the remaining page height and be resized automatically as the browser is resizing. Is it possible to get it done without writing JavaScript code, only with CSS?
I tried to set height:100%
on iframe, the result is quite close but the iframe tried to fill the whole page height, including the 30px
height of banner div element, so I got unnecessary vertical scrollbar. It's not perfect.
I tried CSS margin, padding attribute on DIV to occupy the whole remaining height of a web page successfully, but the trick didn't work on 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>
Solution 1:[1]
We use a JavaScript to solve this problem; here is the source.
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;
Note: ifm
is the iframe ID
pageY()
was created by John Resig (the author of jQuery)
Solution 2:[2]
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.
Example code
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>
Solution 3:[3]
Here are a few modern approaches:
Approach 1 - Combination of viewport relative units /
calc()
.The expression
calc(100vh - 30px)
represents the remaining height. Where100vh
is the height of the browser and the usage ofcalc()
effectively displaces the height of the other element.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>
Support for
calc()
here; support for viewport relative units here.
Approach 2 - Flexbox approach
Set the
display
of the common parent element toflex
, along withflex-direction: column
(assuming you want the elements to stack on top of each other). Then setflex-grow: 1
on the childiframe
element in order for it to fill the remaining space.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>
Since this approach has less support1, I'd suggest going with the aforementioned approach.
1Though it seems to work in Chrome/FF, it doesn't work in IE (the first method works in all current browsers).
Solution 4:[4]
You can do it with DOCTYPE
, but you have to use table
. Check this out:
<!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>
Solution 5:[5]
Maybe this has been answered already (a few answers above are "correct" ways of doing this), but I thought I'd just add my solution as well.
Our iFrame is loaded within a div, hence I needed something else then window.height. And seeing our project already relies heavily on jQuery, I find this to be the most elegant solution:
$("iframe").height($("#middle").height());
Where of course "#middle" is the id of the div. The only extra thing you'll need to do is recall this size change whenever the user resizes the window.
$(window).resize(function() {
$("iframe").height($("#middle").height());
});
Solution 6:[6]
MichAdel code works for me but I made some minor modification to get it work properly.
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;
Solution 7:[7]
Here's what I did. I had the same problem and ended up searching the web for resources for hours.
<style type="text/css">
html, body, div, iframe { margin:0; padding:0; height:100%; }
iframe { position:fixed; display:block; width:100%; border:none; }
</style>
I added this to the head section.
Please note that my iframe is located inside the middle cell of a table that has 3 rows and 1 column.
Solution 8:[8]
Another alternative using vh
<iframe src='/' style="display:block; border:none; height:100vh; width:100%;"></iframe>
Solution 9:[9]
It's right, you are showing an iframe with 100% height respect to its container: the body.
Try this:
<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>
Of course, change the height of the second div to the height you want.
Solution 10:[10]
You can do this with html/css like this:
<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>
Solution 11:[11]
try the following:
<iframe name="" src="" width="100%" style="height: 100em"/>
it worked for me
Solution 12:[12]
New in HTML5: Use calc (on height)
<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>
Solution 13:[13]
I used display:table to fix a similar issue. It almost works for this, leaving a small vertical scroll bar. If you're trying to populate that flexible column with something other than an iframe it works fine (not
Take the following 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>
Change the outer div to use display:table and ensure it has a width and height set.
.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;
}
Add an extra div around your iframe (or whatever content you need) and make it a table-row with height set to 100% (setting its height is critical if you want to embed an iframe to fill the height)
.iframe-container {
display: table-row;
height: 100%;
}
Below is a jsfiddle showing it at work (without an iframe because that doesn't seem to work in the fiddle)
Solution 14:[14]
I think you have a conceptual problem here. To say "I tried set height:100% on iframe, the result is quite close but the iframe tried to fill the whole page", well, when has "100%" not been equal to "whole"?
You have asked the iframe to fill the entire height of its container (which is the body) but unfortunately it has a block level sibling in the <div> above which you've asked to be 30px big. So the parent container total is now being asked to size to 100% + 30px > 100%! Hence scrollbars.
What I think you mean is that you would like the iframe to consume what's left like frames and table cells can, i.e. height="*". IIRC this doesn't exist.
Unfortunately to the best of my knowledge there is no way to effectively mix/calculate/subtract absolute and relative units either, so I think you're reduced to two options:
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.
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.
Solution 15:[15]
Having tried the css route for a while, I ended up writing something fairly basic in jQuery that did the job for me:
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;
}
Tested in IE8, Chrome, Firefox 3.6
Solution 16:[16]
It will work with below mentioned code
<iframe src="http: //www.google.com.tw"style="position: absolute; height: 100%; border: none"></iframe>
Solution 17:[17]
Similar answer of @MichAdel, but I'm using JQuery and more elegant.
<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
is the ID of the iframe tag
Solution 18:[18]
Why not do this (with minor adjustment for body padding/margins)
<script>
var oF = document.getElementById("iframe1");
oF.style.height = document.body.clientHeight - oF.offsetTop - 0;
</script>
Solution 19:[19]
You can do this by measuring the body size on load/resize events and setting the height to the (full height - banner height).
Note that currently in IE8 Beta2 you can't do this onresize as that event is currently broken in IE8 Beta2.
Solution 20:[20]
or you can go old-school and use a frameset perhaps:
<frameset rows="30,*">
<frame src="banner.swf"/>
<frame src="inner.html" />
</frameset>
Solution 21:[21]
While I agree JS seems a better option, I have a somewhat CSS only working solution. The downside of it is that if you have to add content to your iframe html document frequently, you would have to adapt one percentage trough time.
Solution:
Try not specifying any height for BOTH your html documents,
html, body, section, main-div {}
then only code this:
#main-div {height:100%;}
#iframe {height:300%;}
note: the div should be your main section.
This should relatively work. the iframe does exactly calculates 300% of the visible window height. If you html content from the 2nd document (in the iframe) is smaller in height than 3 times your browser height, it works. If you don't need to add content frequently to that document this is a permanent solution and you could just find your own % needed according to your content height.
This works because it prevents the 2nd html document (the one embed) to inherit its height frome the parent html document. It prevents it because we didn't specify an height for both of them. When we give a % to the child it looks for its parent, if not, it takes its content height. And only if the other containers aren't given heights, from what I tried.
Solution 22:[22]
The "seamless" attribute is a new standard aiming to solve this issue:
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
Solution 23:[23]
A simple jQuery solution
Use this in a script inside the iframed page
$(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();
}
}
Solution 24:[24]
you cant set the iframe height in % because your parent body height is not 100% so make the parent height as 100% and then apply iframe height 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>
Solution 25:[25]
If you have access to the content of the iframe that will be loaded, you can tell its parent to resize whenever it resizes..
$(window).resize(function() {
$(parent.document)
.find("iframe")
.css("height", $("body").css("height"));
}).trigger("resize");
If you have more than one iframe on the page, you may need to use id's or other clever methods to enhance .find("iframe") so that you're selecting the correct one.
Solution 26:[26]
I think the best way to achieve this scenario using css position. set position relative to your parent div and position:absolute to your 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>
for other padding and margin issue now a days css3 calc() is very advanced and mostly compatible to all browser as well.
check calc()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow