Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resizing an iframe based on content

I am working on an iGoogle-like application. Content from other applications (on other domains) is shown using iframes.

How do I resize the iframes to fit the height of the iframes' content?

I've tried to decipher the javascript Google uses but it's obfuscated, and searching the web has been fruitless so far.

Update: Please note that content is loaded from other domains, so the same-origin policy applies.

like image 644
larssg Avatar asked Sep 30 '08 14:09

larssg


People also ask

Can iframe be resized?

Next, manually resize the iframe element. The width and height inside the embed code can be adjusted by changing the numbers between the quotation marks, shown below. The standard size of an iframe for desktop is a width of "560" and height of "315."

How do I scale the content of an iframe element?

Use the width, height, padding, and overflow properties to set the dimensions for the "wrap". Use the width, height, and border properties to set the dimensions for the “scaled-frame”. Add the zoom property to scale the content to 75%. Use the transform and transform-origin properties.


1 Answers

We had this type of problem, but slightly in reverse to your situation - we were providing the iframed content to sites on other domains, so the same origin policy was also an issue. After many hours spent trawling google, we eventually found a (somewhat..) workable solution, which you may be able to adapt to your needs.

There is a way around the same origin policy, but it requires changes on both the iframed content and the framing page, so if you haven't the ability to request changes on both sides, this method won't be very useful to you, i'm afraid.

There's a browser quirk which allows us to skirt the same origin policy - javascript can communicate either with pages on its own domain, or with pages it has iframed, but never pages in which it is framed, e.g. if you have:

 www.foo.com/home.html, which iframes  |-> www.bar.net/framed.html, which iframes      |-> www.foo.com/helper.html 

then home.html can communicate with framed.html (iframed) and helper.html (same domain).

 Communication options for each page:  +-------------------------+-----------+-------------+-------------+  |                         | home.html | framed.html | helper.html |  +-------------------------+-----------+-------------+-------------+  | www.foo.com/home.html   |    N/A    |     YES     |     YES     |  | www.bar.net/framed.html |    NO     |     N/A     |     YES     |  | www.foo.com/helper.html |    YES    |     YES     |     N/A     |  +-------------------------+-----------+-------------+-------------+ 

framed.html can send messages to helper.html (iframed) but not home.html (child can't communicate cross-domain with parent).

The key here is that helper.html can receive messages from framed.html, and can also communicate with home.html.

So essentially, when framed.html loads, it works out its own height, tells helper.html, which passes the message on to home.html, which can then resize the iframe in which framed.html sits.

The simplest way we found to pass messages from framed.html to helper.html was through a URL argument. To do this, framed.html has an iframe with src='' specified. When its onload fires, it evaluates its own height, and sets the src of the iframe at this point to helper.html?height=N

There's an explanation here of how facebook handle it, which may be slightly clearer than mine above!


Code

In www.foo.com/home.html, the following javascript code is required (this can be loaded from a .js file on any domain, incidentally..):

<script>   // Resize iframe to full height   function resizeIframe(height)   {     // "+60" is a general rule of thumb to allow for differences in     // IE & and FF height reporting, can be adjusted as required..     document.getElementById('frame_name_here').height = parseInt(height)+60;   } </script> <iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe> 

In www.bar.net/framed.html:

<body onload="iframeResizePipe()"> <iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe>  <script type="text/javascript">   function iframeResizePipe()   {      // What's the page height?      var height = document.body.scrollHeight;       // Going to 'pipe' the data to the parent through the helpframe..      var pipe = document.getElementById('helpframe');       // Cachebuster a precaution here to stop browser caching interfering      pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();    } </script> 

Contents of www.foo.com/helper.html:

<html>  <!--  This page is on the same domain as the parent, so can communicate with it to order the iframe window resizing to fit the content  -->    <body onload="parentIframeResize()">      <script>        // Tell the parent iframe what height the iframe needs to be       function parentIframeResize()       {          var height = getParam('height');          // This works as our parent's parent is on our domain..          parent.parent.resizeIframe(height);       }        // Helper function, parse param from request string       function getParam( name )       {         name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");         var regexS = "[\\?&]"+name+"=([^&#]*)";         var regex = new RegExp( regexS );         var results = regex.exec( window.location.href );         if( results == null )           return "";         else           return results[1];       }     </script>    </body>  </html> 
like image 178
ConroyP Avatar answered Sep 24 '22 08:09

ConroyP