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>
given the iframe is directly under body. If the iframe has a parent between itself and the body, the iframe will still get the height of its parent. One must explicitly set the height of every parent to 100% as well (if that's what one wants).
You can use the JavaScript contentWindow property to make an iFrame automatically adjust its height according to the contents inside it, so that no vertical scrollbar will appear.
The ” iframe ” tag defines a rectangular region within the document in which the browser can display a separate document, including scrollbars and borders. An inline frame is used to embed another document within the current HTML document. For the fullscreen Iframe, you have to cover the entire viewport.
TL;DR: Today the best option is - flexbox. Everything supports it nicely and has for years. Go for that and don't look back. Here is a code sample for 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 trick is to understand what the 100% is taken of. Reading CSS specs can help you there.
To make a long story short - there is such a thing as "containing block" - which is not necessary the parent element. Simply said, it is the first element up the hierarchy that has position:relative or position:absolute. Or the body element itself if there is nothing else. So, when you say "width: 100%", it checks the width of the "containing block" and sets the width of your element to the same size. If there was something else there, then you might get contents of a "containing block" that are larger than itself (thus "overflowing").
Height works the same way. With one exception. You can't get height to 100% of the browser window. The very top level element, against which 100% can be calculated, is the body (or html? not sure) element, and that stretches just enough to contain its contents. Specifying height:100% on it will have no effect, because it has no "parent element" against which to measure 100%. Window itself doesn't count. ;)
To make something stretch exactly 100% of the window, you have two choices:
Update: I'm not sure if I wasn't wrong already when I posted this, but this certainly is outdated now. Today you can do this in your stylesheet: html, body { height: 100% }
and it will actually stretch to the whole of your viewport. Even with a DOCTYPE. min-height: 100%
could also be useful, depending on your situation.
And I wouldn't advise anyone to make a quirks-mode document anymore either, because it causes way more headaches than solves them. Every browser has a different quirks-mode, so getting your page to look consistently across browsers becomes two orders of magnitude more difficult. Use a DOCTYPE. Always. Preferably the HTML5 one - <!DOCTYPE html>
. It's easy to remember and works like a charm in all browsers, even the 10 years old ones.
The only exception is when you have to support something like IE5 or something. If you're there, then you're on your own anyway. Those ancient browsers are nothing like the browsers today, and little advice that is given here will help you with them. On the bright side, if you're there, you probably just have to support ONE kind of browser, which gets rid of the compatibility problems.
Good luck!
Update 2: Hey, it's been a long time! 6 years later, new options are on the scene. I just had a discussion in the comments below, here are more tricks for you that work in today's browsers.
Option 1 - absolute positioning. Nice and clean for when you know the precise height of the first part.
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>
Some notes - the second-row
container is needed because bottom: 0
and right: 0
doesn't work on iframes for some reason. Something to do with in being a "replaced" element. But width: 100%
and height: 100%
works just fine. display: block
is needed because it's an inline
element by default and whitespace starts creating weird overflows otherwise.
Option 2 - tables. Works when you don't know the height of the first part. You can use either actual <table>
tags or do it the fancy way with display: table
. I'll go for the latter because it seems to be in fashion these days.
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>
Some notes - the overflow: auto
makes sure that the row always includes all of its contents. Otherwise floating elements can sometimes overflow. The height: 100%
on the second row makes sure it expands as much as it can squeezing the first row as small as it gets.
Recommended: Option 3 - flexbox - The cleanest one of them all.
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>
Some notes - the overflow: hidden
is because the iframe still generates some sort of overflow even with display: block
in this case. It isn't visible in the fullscreen view or the snippet editor, but the small preview window gets an extra scrollbar. No idea what that is, iframes are weird.
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)
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>
calc()
.The expression calc(100vh - 30px)
represents the remaining height. Where 100vh
is the height of the browser and the usage of calc()
effectively displaces the height of the other element.
Example Here
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.
Example Here
Set the display
of the common parent element to flex
, along with flex-direction: column
(assuming you want the elements to stack on top of each other). Then set flex-grow: 1
on the child iframe
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).
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>
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());
});
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;
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.
Another alternative using vh
<iframe src='/' style="display:block; border:none; height:100vh; width:100%;"></iframe>
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.
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>
try the following:
<iframe name="" src="" width="100%" style="height: 100em"/>
it worked for me
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>
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)
https://jsfiddle.net/yufceynk/1/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With