Monday, November 22, 2010

Zooming an IFrame in IE

Today I was working with one of our designers to fix some iframe zooming in an Internet Explorer application. Unfortunately the zoom property is not supported by any other browsers than IE (I wish it was, and any suggestions are welcome!!).
Basically we wanted the iframeto be of a certain size and then zoom its page to that size. It sounds really easy… but...

This is the HTML we want to use:

Preview:<br/>
<iframe id="tst" style="border:0; width:500px;height:200px;" src="http://sites.google.com/a/googleuniversity.org/ski-club/Home/About-the-Club" >
<p>Your browser does not support tampering with iframe content.</p>
</iframe>

That will result in:


In this post I will explain how to accomplish zooming the page as a minified preview of what it would look like if the page would be shown in a "normal" browser window. I will be using some jQuery because it solves a lot of nasty javascript problems for me and it makes the code easier to understand and read.

Problems
There are three mail problems to tackle:

  1. Zooming the page.
  2. The dimensions of the page (in a normal browser, the page looks very different).
  3. Scrolling / breaking out of the page.
Zooming
Solving the first problem is very easy: zooming can be achieved by adding a css attribute to iframe. But in order to get the zoom-factor, we need to do some calculation on the actual size of the document. This can be done by this code:
$(document).ready(function () {

 $('iframe').load(function () {
  var $frame = $(this);

  if ($frame[0].document) {

   var w = $frame.width();
   var zw = w / $($frame[0].document.body).width();

   //set to iframe
   $frame.css({ 'width': w, 'zoom': (zw * 100) + '%', 'overflow': 'visible' });
   $frame.show();
  }
  else {
   $frame.replaceWith($($frame.text()));
  }
 });
});

Resulting in:

Document dimensions
It is not only the page that has been zoomed, but the entire iframe element has been adjusted. We need to write up some more code to correct the height and width of the element itself. We'll wrap the iframe in a div and copy the height and the width of the iframe to the div. After that we'll correct the iframe for zooming by making it's width equal to (w*(1/z)).

$(document).ready(function () {

 //get elements
 $('iframe').load(function () {

  var $frame = $(this);

  if ($frame[0].document) {

   //wrap the iframe in a div
   var $div = $('<div class="framewrapper" />');
   $frame.wrap($div);
   $div = $frame.parent();

   //get container properties
   var w = $frame.width();
   var h = $frame.height();

   //calculate zoom
   var zw = w / $($frame[0].document.body).width();
   var zh = h / $($frame[0].document.body).height();

   //set container properties
   $div.css({ 'display': 'block', 'width': w, 'height': h });

   //calculate document properties
   w = Math.floor(w * (1 / zw));
   h = Math.floor(h * (1 / zh));

   //set to iframe
   $frame.css({ 'width': w, 'height': h, 'zoom': (zw * 100) + '%' }); 
   $frame.show();
  }
  else {
   $frame.replaceWith($($frame.text()));
  }
 });
});

Resulting in:

Scrolling / iframe size
The result looks okay, but don't get fooled! The iframe breaks out of the div. And even if we make the iframe smaller, we will see tiny zoomed scroll bars! That's why we need to add some good old CSS-overflow styling!

$(document).ready(function () {

 //get elements
 $('iframe').load(function () {

  var $frame = $(this);

  if ($frame[0].document) {

   //wrap the iframe in a div
   var $div = $('<div class="framewrapper" />');
   $frame.wrap($div);
   $div = $frame.parent();

   //get container properties
   var w = $frame.width();
   var h = $frame.height();

   //calculate zoom
   var zw = w / $($frame[0].document.body).width();
   var zh = h / $($frame[0].document.body).height();

   //set container properties
   $div.css({
    'display': 'block',
    'overflow': 'scroll',
    'width': w,
    'height': h,
    //width/x is '100%', hide scrolling    
    'overflow-x': 'hidden', 
    //height/y should scroll
    'overlow-y': 'scroll' 
   });

   //calculate document properties
   w = Math.floor(w * (1 / zw));
   h = Math.floor(h * (1 / zh));

   //set to iframe
   $frame.css({
    'width': w,
    'height': h,
    'zoom': (zw * 100) + '%',
    //make sure the document has NO scrollbars!
    'overflow': 'visible'
   });
     
   $frame.show();
  }
  else {
   $frame.replaceWith($($frame.text()));
  }
 });

});

Resulting in:

And that is how it's done. If anybody out there knows a better (cross browser) way of zooming iframes, please do tell me! As always... comments / suggestions are welcome.

1 comment:

  1. very helpful for me as I am currently developing on an intranet where client browsers are exclusively IE. thanks.

    -Brian

    ReplyDelete

Please feel free to leave a comment. When you are using the option to react anonymous, please add your name to the comment ;-).