Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Make iframe 100% height according to its content

Tags:

html

css

iframe

I had seen a lot of people asking how to make iframe 100% height. That can be easily archived using some CSS. It will make the iframe display 100% as relative to the device screen. But how to make iframe 100% height according to its content?

Here's my current code to make 100% iframe according to device screen:

        iframe {
        display: block;
        background: #000;
        border: none;
        height: 100vh;
        width: 100vw;
    }
    <iframe src="https://...">Your Browser Does Not Support iframes!</iframe>

The allowfullscreen and position:absolute didn't help except for crashing my site's template. This is the best I can do without crashing the primary CSS. Please help...

Edit: The iframe content is responsive using

<meta name="viewport" content="width=device-width,initial-scale=1">

so preset height using javascript didn't work too. Perhaps is there a way of using height units instead?

em, ex, rem etc? Or make it a specific percentage of vw?

like image 755
Anthony Kung Avatar asked Mar 13 '18 10:03

Anthony Kung


People also ask

How to set iframe height according to its content?

There is no CSS only way to set iframe height according to its content. You need to use JavaScript to get iframe content height and then set as iframe height. how to achieve this using JavaScript answered and well explained in the following questions: Make iframe automatically adjust height according to the contents without using scrollbar?

What does the second half of an iframe set to?

The second half sets the iframe to page height (not content height), when iframes class is iframe_fullHeight. You can use this if the content is a PDF or other such like, but you have to set the class.

How to make an iframe dynamic in JavaScript?

There is a way to make it dynamically by using some attribute of JavaScript. The attributes used here are, contentWindow : This property returns the Window object used by an iframe element, basically its defines the iframe window. scrollHeight : This property defines the entire height of an element in pixels, the element is iframe.

Should iframes be fullscreen or not?

All this does is makes a fullscreen iframe, which is definitely not what most people want. This also goes against the HTML5 spec, which says that height and width of an iframe must be in pixels, not percent (however percent is perfectly fine for HTML 4.01).


1 Answers

Just wanted to share my solution and excitement. It took me four entire days of intensive research and failure, but I think I've found a neat way of making iframes entirely responsive! Yey!

I tried a ton of different approaches... I didn't want to use a two-way communication tunnel as with postMessage because it's awkward for same-origin and complicated for cross-origin (as no admin wants to open doors and implement this on your behalf).

I've tried using MutationObservers and still needed several EventListeners (resize, click,..) to ensure that every change of the layout was handled correctly. - What if a script toggles the visibility of an element? Or what if it dynamically preloads more content on demand? - Another issue was getting an accurate height of the iframe contents from somewhere. Most people suggest using scrollHeight or offsetHeight, or combination of it by using Math.max. The problem is, that these values don't get updated until the iframe element changes its dimensions. To achieve that you could simply reset the iframe.height = 0 before grabbing the scrollHeight, but there are even more caveats to this. So, screw this.

Then, I had another idea to experiment with requestAnimationFrame to get rid of my events and observers hell. Now, I could react to every layout change immediately, but I still had no reliable source to infer the content height of the iframe from. And theeen I discovered getComputedStyle, by accident! This was an enlightenment! Everything just clicked.

Well, see the code I could eventually distill from my countless attempts.

function fit() {
    var iframes = document.querySelectorAll("iframe.gh-fit")

    for(var id = 0; id < iframes.length; id++) {
        var win = iframes[id].contentWindow
        var doc = win.document
        var html = doc.documentElement
        var body = doc.body
        var ifrm = iframes[id] // or win.frameElement

        if(body) {
            body.style.overflowX = "scroll" // scrollbar-jitter fix
            body.style.overflowY = "hidden"
        }
        if(html) {
            html.style.overflowX = "scroll" // scrollbar-jitter fix
            html.style.overflowY = "hidden"
            var style = win.getComputedStyle(html)
            ifrm.width = parseInt(style.getPropertyValue("width")) // round value
            ifrm.height = parseInt(style.getPropertyValue("height"))
        }
    }

    requestAnimationFrame(fit)
}

addEventListener("load", requestAnimationFrame.bind(this, fit))

That is it, yes! - In your HTML code write <iframe src="page.html" class="gh-fit gh-fullwidth"></iframe>. The gh-fit is a just fake CSS class, used to identify which iframe elements in your DOM should be affect by the script. The gh-fullwidth is a simple CSS class with one rule width: 100%;.

The above script automatically fetches all iframes from the DOM, that have a .gh-fit class assigned. It then grabs and uses the pre-calculated style values for width and height from document.getComputedStyle(iframe), which always contain a pixel-perfect size of that element!!! Just perfect!

Note, this solution doesn't work cross-origin (nor does any other solution, without a two-way communication strategy like IFrameResizer). JS simply can't access the DOM of an iframe, if it doesn't belong to you.

The only other cross-origin solution I can think of, is to use a proxy like https://github.com/gnuns/allorigins. But this would involve deep-copying every request you make - in other words - you 'steal' the entire page source code (to make it yours and let JS access the DOM) and you patch every link/path in this source, so that it goes through the proxy as well. The re-linking routine is a tough one, but doable.

I'll probably try myself at this cross-origin problem, but that's for another day. Enjoy the code! :)

like image 131
geekhunger Avatar answered Oct 12 '22 15:10

geekhunger