337

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>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Darkthread
  • 4,109
  • 5
  • 33
  • 137

27 Answers27

322

Update in 2019

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 rest of this answer is left for learning & historical reasons.


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:

  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.

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.

Ronen Rabinovici
  • 8,680
  • 5
  • 34
  • 46
Vilx-
  • 104,512
  • 87
  • 279
  • 422
  • @sproketboy Well, it's a W3C recommendation. And it's not even the worst, not by a long way. – John Jan 16 '15 at 12:08
  • So do we put this in the stylesheet of the IFrame's page, or the stylesheet of the parent page that contains the IFrame? – Mathias Lykkegaard Lorenzen Mar 07 '15 at 17:15
  • @sproketboy - css was originally mostly a text formatting language with basic layout functionality that was still actually text-centric - it just turned out to be better than tables for layout hence it's adoption - in many ways we've been hacking layouts ever since – Toni Leigh Jun 15 '15 at 11:52
  • @ToniLeigh No, tables have generally been much better for layout. They work consistently across all browsers. The only reason CSS has layout aspects is that it was designed by sociopaths. – sproketboy Sep 16 '15 at 17:56
  • @sproketboy css works consistently across browsers if you know what you're doing, the basic layout stuff is all early css; tables on the other hand cause mark-up soup and drag a lot of display stuff into the HTML, which is incorrect – Toni Leigh Sep 16 '15 at 18:30
  • @ToniLeigh - IMHO, when you want fluid layouts (which choose their size according to the size of their contents and sibling elements affect each other), then tables are pretty much the only solution. Sure, you can do `display:table-layout`, but you'll just replace one tag soup with another, because all the tags for tables/rows/cells will still be needed. Then again, such layouts are pretty rare, and in my experience 90% of case can be resolved without resorting to tables. – Vilx- Sep 16 '15 at 22:23
  • @ToniLeigh - Nevertheless, this is getting pretty far offtopic, don't you think? :) – Vilx- Sep 16 '15 at 22:24
  • @Vilx Yes, it's off topic, but the original statement about tables wasn't me and was so far off the mark in 2015 I had to say something. I've never encountered a situation except for tabular data that's better done with tables, if you could show me one I'd be very interested – Toni Leigh Sep 17 '15 at 05:41
  • @ToniLeigh - Well, how about this: make a horizontal menu with a list of links next to each other. The links are supplied dynamically so you don't know ahead of time what they are. The menu should be visible all at the same time - if there is not enough horizontal space, the text should start wrapping in some items. No horizontal scrolling is allowed, unless something else in the page forces it. Also, some links may have newlines in them. All the links should have a visible border and all these "boxes" should be the same height. The text in them should be centered vertically. – Vilx- Sep 17 '15 at 23:36
  • @ToniLeigh - Note that the wrapping can also be introduced when the user starts resizing the browser window. All the boxes should change their height simultaneously then and the text should be kept vertically centered in all of them. – Vilx- Sep 17 '15 at 23:38
  • @Vilx- it sounds like you're describing a horizontal bar nav that behaves exactly like a table row. This is an excellent example of good use of the table display css properties. This would leave you able to mark up the HTML in a much more sensible way: ` – Toni Leigh Sep 18 '15 at 06:35
  • @ToniLeigh - Yes, but, as I said, now you've just replaced one tag soup for another. You're still using a table (the browser processes it as such), but just to confuse the unwary code maintainer, it's masquerading as a ` – Vilx- Sep 19 '15 at 06:05
  • @Vilx- I've used the correct mark-up for navigation, I haven't confused the maintainer because they'll find navigation in the markup for navigation, neither have confused any mechanical HTML processors, again for the same reason. Imagine if I used tables for everything on a webpage? How difficult would that be to maintain? It's not tag soup either, because each tag is there for a reason, with purpose: nav to mark the area as a navigation panel; and UL and LI to mark an unordered list. The browser uses table-like display properties, but that's it. – Toni Leigh Sep 19 '15 at 07:15
  • @Vilx- yes, a css property such as `action: post;` would be wrong; the thing is though, that tables have no functionality. Inputs and As both have functionality and act as markup tags: an input acts as part of a post; an a renders a hyperlink; but a table doesn't do anything, it's just mark-up. In fact, As and Inputs both have styles attached too, we get rid of them using reset.css usually. What you're suggesting is kind of like using an A to mark text because you'd like it to be the default blue. The display properties of a table belong in the section of code that defines how the site looks. – Toni Leigh Sep 19 '15 at 10:32
  • @Vilx- and thanks, there's a nuance to your argument that might be missed by a tub-thumper that has really made me think this morning :-) – Toni Leigh Sep 19 '15 at 10:33
  • @ToniLeigh - you're welcome. :) About tables being just layout - I'm... not so sure. Well, I guess... but it's such and advanced sort of layout that nothing else comes close to. In essence, unrelated elements affect each other's size. Everywhere else there has to be a parent-child relationship between two elements to affect their size. But not in tables. Colspans/rowspans make it even more complicated. And then there's the thing about `display: table-head-group` which makes it print on every page. Isn't that extra functionality, not just layout? – Vilx- Sep 19 '15 at 22:06
  • All these "naive" styles do not help for `iframe`, unfortunately. – Dmitri Zaitsev Apr 19 '17 at 13:57
  • @DmitriZaitsev - It works for me. `body, html, iframe {width: 100%; height: 100%; border: none; padding: 0; margin: 0}` - and you have a full-page iframe. What doesn't work for you? – Vilx- Apr 19 '17 at 15:25
  • Yes, but the double scrollbar is somewhat unfortunate: http://jsbin.com/rixakir/edit?html,css,output – Dmitri Zaitsev Apr 20 '17 at 02:12
  • @DmitriZaitsev - Ahh, wait, I forgot what the original question was about. :) [Here's one solution](https://jsfiddle.net/yykg0qm1/), using absolute positioning (my favorite). You can also get a similar effect using a `` or `display: table-row` which allows for a more dynamic sizing at the cost of a little bit of performance. Anyways, the basic idea in all of them are - create some wrapper elements that stretch the way you need, and then position the iframe inside with `width: 100%; height: 100%; margin: 0; padding: 0; border: none`.
    – Vilx- Apr 20 '17 at 08:38
  • The problem with absolute positioning, if I see it correctly, is that in practice you don't know where to set the top and the bottom. The height of the first container is merely determined by its content, so I don't see any way to reliably set its height, nor the top of the iframe container. Here is my attempt to remove those settings and the result is the whole iframe is gone: https://jsfiddle.net/t1h0zwoq/ – Dmitri Zaitsev Apr 20 '17 at 13:13
  • @DmitriZaitsev - You mean the second row is gone? Anyway, if the size of the first panel isn't known, then you can use that table trick I talked about. Here's an example: https://jsfiddle.net/t1h0zwoq/2/. I style the `
    `s as tables and make them stretch as needed. The `overflow:auto` on the first row makes sure it will always stretch to its contents. The `height: 100%` on the second row means that it will stretch to whatever is left after the first row. And the `display:block` on the `
    – Vilx- Apr 20 '17 at 13:44
  • @DmitriZaitsev - And, actually, let's not forget good old flexbox. This is actually the cleanest solution: https://jsfiddle.net/t1h0zwoq/3/ Mind you, browser support isn't that stellar, in particular if you're interested in old versions of IE. IE10 needs the `-ms-` prefix and IE9 doesn't support it at all. Other than that it's great. – Vilx- Apr 20 '17 at 13:56
  • 1
    That is awesome, thank you! The flexbox the the cleanest indeed, but the tables are also great to learn and seem to work without the overflows: https://jsfiddle.net/dmitri14/1uqh3zgx/2/ – Dmitri Zaitsev Apr 20 '17 at 16:06
  • @DmitriZaitsev - I updated the answer too. And, yes, it's possible that a few of those `overflow`s are not necessary. But check for yourself - today I myself learned that `iframe`s are a lot more finicky than would appear at the first glance. – Vilx- Apr 20 '17 at 16:26
  • Many thanks for the update! It is finicky indeed, which would have been the reason for this question I suppose. Yes, both `overflows` can be uncommented with the whole thing working beautifully with almost no css: https://jsfiddle.net/dmitri14/1uqh3zgx/3/ – Dmitri Zaitsev Apr 21 '17 at 15:29
  • 1
    It might be worth moving the latest updates to the top of this answer. I had to go through the whole thing to get to the best answer, flexbox. – forgivenson Mar 29 '19 at 21:31
  • 2
    @forgivenson - True enough. Added a note at the start of this answer. – Vilx- Mar 30 '19 at 01:28
  • With flexbox, [you can make iframes resizable](https://stackoverflow.com/a/60803488/490291), [even in Firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=680823). – Tino Mar 22 '20 at 18:56
  • @DmitriZaitsev I added "overflow: hidden;" to the "body, html" rule, and that removed the doubled scroll bar. Now, the iframe can scroll, but the redundant scroll bar on the body is gone. I recommend updating the solution with this fix. Otherwise, the flexbox solution is perfect for a back-end dashboard where you have a wrapping menu bar of buttons at the top, and the remaining area is an iframe for content. – humbads Jul 14 '20 at 13:27
71

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)

Flexo
  • 2,506
  • 3
  • 21
  • 32
MichAdel
  • 737
  • 4
  • 3
53

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>
JIBIN BJ
  • 105
  • 15
D1SoveR
  • 567
  • 4
  • 8
43

Here are a few modern approaches:


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


  • Approach 2 - Flexbox approach

    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).

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • 3
    Both work and IMO the two options mentioned here are best approach. I prefer the `flexbox` option because with `calc` you need to know the amount of space to deduct from the `vh`. With `flexbox` a simple `flex-grow:1` does it. – Kilmazing Jan 06 '17 at 16:01
39

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>
Mohammad Faisal
  • 5,783
  • 15
  • 70
  • 117
ducu
  • 1,199
  • 2
  • 12
  • 14
18

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());
});
Tim Geerts
  • 311
  • 5
  • 14
6

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.

ARemesal
  • 2,923
  • 5
  • 24
  • 23
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;
asimrafi
  • 61
  • 1
  • 1
6

Another alternative using vh

<iframe src='/' style="display:block; border:none; height:100vh; width:100%;"></iframe>
montrealmike
  • 11,433
  • 10
  • 64
  • 86
6

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.

Danut Milea
  • 89
  • 1
  • 3
  • Your code will only work either the TD containing the IFRAME has height:100%. It will work if the table is contained within a DIV element, because you have a style for all the divs to have height:100%. – Nikola Petkanski Dec 14 '11 at 11:17
3

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>
vdbuilder
  • 12,254
  • 2
  • 25
  • 29
2

try the following:

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

it worked for me

sree
  • 543
  • 6
  • 21
2

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>
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
2

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/

daamsie
  • 1,539
  • 10
  • 15
1

It will work with below mentioned code

<iframe src="http: //www.google.com.tw"style="position: absolute; height: 100%; border: none"></iframe>
mgr
  • 641
  • 1
  • 8
  • 23
1

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

Roy Shmuli
  • 4,979
  • 1
  • 24
  • 38
1

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:

  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.

Diodeus - James MacFarlane
  • 112,730
  • 33
  • 157
  • 176
annakata
  • 74,572
  • 17
  • 113
  • 180
1

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

benb
  • 733
  • 7
  • 18
1

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>
access_granted
  • 1,807
  • 20
  • 25
0

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.

pixelfe
  • 11
  • 3
0

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

Community
  • 1
  • 1
user2254487
  • 171
  • 2
  • 4
0

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();
    }

}
unloco
  • 6,928
  • 2
  • 47
  • 58
0

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>
Pravin Abhale
  • 395
  • 2
  • 4
  • 15
0

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.

Stephen
  • 3,341
  • 1
  • 22
  • 21
0

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.

scunliffe
  • 62,582
  • 25
  • 126
  • 161
0

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()

Jay Patel
  • 5,783
  • 1
  • 17
  • 20
0

or you can go old-school and use a frameset perhaps:

<frameset rows="30,*">
  <frame src="banner.swf"/>
  <frame src="inner.html" />
</frameset>
Amir Arad
  • 6,724
  • 9
  • 42
  • 49