290

How can I scale the content of an iframe (in my example it is an HTML page, and is not a popup) in a page of my web site?

For example, I want to display the content that appears in the iframe at 80% of the original size.

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
John Griffiths
  • 3,263
  • 4
  • 21
  • 19

18 Answers18

250

Kip's solution should work on Opera and Safari if you change the CSS to:

<style>
    #wrap { width: 600px; height: 390px; padding: 0; overflow: hidden; }
    #frame { width: 800px; height: 520px; border: 1px solid black; }
    #frame {
        -ms-zoom: 0.75;
        -moz-transform: scale(0.75);
        -moz-transform-origin: 0 0;
        -o-transform: scale(0.75);
        -o-transform-origin: 0 0;
        -webkit-transform: scale(0.75);
        -webkit-transform-origin: 0 0;
    }
</style>

You might also want to specify overflow: hidden on #frame to prevent scrollbars.

Community
  • 1
  • 1
lxs
  • 8,847
  • 4
  • 20
  • 19
  • @JonathanM - cf http://meta.stackexchange.com/questions/75043/what-is-the-right-way-to-elaborate-on-an-answer, did I do something wrong here? – lxs Mar 19 '12 at 11:54
  • @lxs, Not at all. I loved it, and gave it a +1. Good job. – Jonathan M Mar 27 '12 at 00:20
  • 8
    I have noticed that on chrome I get both the zoom and the webkit transform applied which causes the scale to be applied twice. – dennisjtaylor Jan 18 '13 at 23:43
  • event with the -ms-zoom prefix, I have issues on safari iPad (perhaps thats asking too much!) – Andiih Apr 30 '13 at 11:20
  • 1
    as @dennisjtaylor says, chrome seems to apply the scale twice - as seen here http://jsfiddle.net/zjTBq/embedded/result/ – Horse Aug 14 '13 at 16:25
  • As @r3cgm's [answer](http://stackoverflow.com/a/7504903/304282) says, replacing zoom with -ms-zoom should sort this out. Don't know if this will break EG IE6. You could also try removing the -webkit-transform lines. – lxs Aug 22 '13 at 12:59
  • @Andiih, no idea why Safari on iPad is special sorry – lxs Aug 22 '13 at 12:59
  • I had a hard time wrapping my head around how that'd work if I wanted to control scale of an entire viewport. Here is a SCSS snippet. https://gist.github.com/gajus/6b6c49c3c3a0282f4b9d This assumes that all contents below `body` is contained in `#viewport`. – Gajus Sep 20 '15 at 17:15
  • Beware, using scale transforms can cause problems with js based/pixelbased interaction types such as draggable and order. I'm working on a similar issue and have thusfar noticed some of those still work just fine when using em units, but not with scale transforms. – Koert van Kleef Apr 20 '16 at 10:35
  • 3
    As all modern browsers have been supporting transform for quite a while I would consider using the unprefixed version (at least as an alternative). – wortwart Nov 12 '16 at 20:28
  • You can also use `width: calc(600px / 0.75); height: calc(390px / 0.75);` for the iframe sizing. – Shane Creighton-Young Dec 21 '18 at 20:45
  • 1
    These days, is there any advantage to using ALL of those instead of just "transform" and "transform-origin"? Are there still people using browsers that wouldn't support that and would be helped by lxs's version? I noticed that StretchVideo.js, a nice 2018 bookmarklet that changes the aspect ratio of online videos uses only "transform" and "transform-origin": https://gist.github.com/arpruss/74abc1bc95ae08e543b9b74f15a23b07 http://alexanderpruss.blogspot.com/2018/08/adjust-aspect-ratio-of-online-videos.html – Esn024 Apr 16 '21 at 06:10
  • Thanks @Esn024 - that was the solution I needed. Same approach for wrapper and the `width` and `height` of iframe, but I just used `transform` and `transform-origin` and was able to omit everything else. – Willow Feb 28 '22 at 19:07
  • It just resizes the iframe for me !!! – Codie Aug 03 '22 at 15:38
59

I found a solution that works in IE and Firefox (at least on the current versions). On Safari/Chrome, the iframe is resized to 75% of its original size, but the content within the iframe is not scaled at all. In Opera, this doesn't seem to work. This feels a bit esoteric, so if there is a better way to do it I'd welcome suggestions.

<style>
#wrap { width: 600px; height: 390px; padding: 0; overflow: hidden; }
#frame { width: 800px; height: 520px; border: 1px solid black; }
#frame { zoom: 0.75; -moz-transform: scale(0.75); -moz-transform-origin: 0 0; }
</style>

...

<p>Some text before the frame</p>
<div id="wrap">
<iframe id="frame" src="test2.html"></iframe>
</div>
<p>Some text after the frame</p>
</body>

Note: I had to use the wrap element for Firefox. For some reason, in Firefox when you scale the object down by 75%, it still uses the original size of the image for layout reasons. (Try removing the div from the sample code above and you'll see what I mean.)

I found some of this from this question.

Community
  • 1
  • 1
Kip
  • 107,154
  • 87
  • 232
  • 265
38

After struggling with this for hours trying to get it to work in IE8, 9, and 10 here's what worked for me.

This stripped-down CSS works in FF 26, Chrome 32, Opera 18, and IE9 -11 as of 1/7/2014:

.wrap
{
    width: 320px;
    height: 192px;
    padding: 0;
    overflow: hidden;
}

.frame
{
    width: 1280px;
    height: 786px;
    border: 0;

    -ms-transform: scale(0.25);
    -moz-transform: scale(0.25);
    -o-transform: scale(0.25);
    -webkit-transform: scale(0.25);
    transform: scale(0.25);

    -ms-transform-origin: 0 0;
    -moz-transform-origin: 0 0;
    -o-transform-origin: 0 0;
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
}

For IE8, set the width/height to match the iframe, and add -ms-zoom to the .wrap container div:

.wrap
{
    width: 1280px; /* same size as frame */
    height: 768px;
    -ms-zoom: 0.25; /* for IE 8 ONLY */
}

Just use your favorite method for browser sniffing to conditionally include the appropriate CSS, see Is there a way to do browser specific conditional CSS inside a *.css file? for some ideas.

IE7 was a lost cause since -ms-zoom did not exist until IE8.

Here's the actual HTML I tested with:

<div class="wrap">
   <iframe class="frame" src="http://time.is"></iframe>
</div>
<div class="wrap">
    <iframe class="frame" src="http://apple.com"></iframe>
</div>

http://jsfiddle.net/esassaman/PnWFY/

Community
  • 1
  • 1
Eric Sassaman
  • 1,401
  • 1
  • 18
  • 23
34

I just tested and for me, none of the other solutions worked. I simply tried this and it worked perfectly on Firefox and Chrome.

<div class='wrap'>
  <iframe ...></iframe>
</div>

and the css:

.wrap {
  width: 640px;
  height: 480px;
  overflow: hidden;
}

iframe {
  width: 76.92% !important;
  height: 76.92% !important;
  -webkit-transform: scale(1.3);
  transform: scale(1.3);
  -webkit-transform-origin: 0 0;
  transform-origin: 0 0;
}

This scales all the content by 23.08%, the equivalent of the original being 30% larger than the embedded version. (The width/height percentages of course need to be adjusted accordingly (1/scale_factor)).

MrP01
  • 1,425
  • 13
  • 20
  • 4
    You also want to add `overflow: hidden;` to the `.wrap` element. When you use `iframe { width: 200%; height: 200%; transform: scale(0.5); }` iframe starts overflowing. – ozgrozer Mar 21 '19 at 07:04
14

You don't need to wrap the iframe with an additional tag. Just make sure you increase the width and height of the iframe by the same amount you scale down the iframe.

e.g. to scale the iframe content to 80% :

#frame { /* Example size! */
    height: 400px; /* original height */
    width: 100%; /* original width */
}
#frame {
    height: 500px; /* new height (400 * (1/0.8) ) */
    width: 125%; /* new width (100 * (1/0.8) )*/

    transform: scale(0.8); 
    transform-origin: 0 0;
}

Basically, to get the same size iframe you need to scale the dimensions.

Matthew Wilcoxson
  • 3,432
  • 1
  • 43
  • 48
10

Followup to lxs's answer: I noticed a problem where having both the zoom and --webkit-transform tags at the same time seems to confound Chrome (version 15.0.874.15) by doing a double-zoom sort of effect. I was able to work around the issue by replacing zoom with -ms-zoom (targeted only at IE), leaving Chrome to make use of just the --webkit-transform tag, and that cleared things up.

Community
  • 1
  • 1
r3cgm
  • 133
  • 1
  • 7
9

With CSS:

html{
    zoom:0.4;
}

?-)

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
roenving
  • 2,560
  • 14
  • 14
  • 3
    It would be 0.8 for 80%, but that is a proprietary Microsoftism, so probably not suitable. It would also only work if the document loaded into the frame could be edited, which is unlikely. – Quentin Oct 03 '08 at 16:14
8

Thought I'd share what I came up with, using much of what was given above. I haven't checked Chrome, but it works in IE, Firefox and Safari, so far as I can tell.

The specifics offsets and zoom factor in this example worked for shrinking and centering two websites in iframes for Facebook tabs (810px width).

The two sites used were a wordpress site and a ning network. I'm not very good with html, so this could probably have been done better, but the result seems good.

<style>
    #wrap { width: 1620px; height: 3500px; padding: 0; position:relative; left:-100px; top:0px; overflow: hidden; }
    #frame { width: 1620px; height: 3500px; position:relative; left:-65px; top:0px; }
    #frame { -ms-zoom: 0.7; -moz-transform: scale(0.7); -moz-transform-origin: 0px 0; -o-transform: scale(0.7); -o-transform-origin: 0 0; -webkit-transform: scale(0.7); -webkit-transform-origin: 0 0; }
</style>
<div id="wrap">
    <iframe id="frame" src="http://www.example.com"></iframe>
</div>
Mihai Iorga
  • 39,330
  • 16
  • 106
  • 107
Jon Fergus
  • 171
  • 1
  • 9
  • I just tried this with Chrome v110 and found it works perfectly, thank you for a solution to my headache :). I did find that if you want to scale a realistic page down, change the width of the #wrap and #frame to 1920px as that’s the standard view of most websites on a PC and remove the positioning of left:-100px from #wrap and left:-65px from #frame and change those PX values to 0px so the page fits in full and then delete the position: element in both #frame and #wrap and instead, add positioning details to the containing DIV so you can easily move the scaled iframe around your page. – David Crawford Mar 03 '23 at 10:41
6

If you want the iframe and its contents to scale when the window resizes, you can set the following to the window's resize event as well as the iframes onload event.

function()
{
    var _wrapWidth=$('#wrap').width();
    var _frameWidth=$($('#frame')[0].contentDocument).width();

    if(!this.contentLoaded)
      this.initialWidth=_frameWidth;
    this.contentLoaded=true;
    var frame=$('#frame')[0];

    var percent=_wrapWidth/this.initialWidth;

    frame.style.width=100.0/percent+"%";
    frame.style.height=100.0/percent+"%";

    frame.style.zoom=percent;
    frame.style.webkitTransform='scale('+percent+')';
    frame.style.webkitTransformOrigin='top left';
    frame.style.MozTransform='scale('+percent+')';
    frame.style.MozTransformOrigin='top left';
    frame.style.oTransform='scale('+percent+')';
    frame.style.oTransformOrigin='top left';
  };

This will make the iframe and its content scale to 100% width of the wrap div (or whatever percent you want). As an added bonus, you don't have to set the css of the frame to hard coded values since they'll all be set dynamically, you'll just need to worry about how you want the wrap div to display.

I've tested this and it works on chrome, IE11, and firefox.

user3298597
  • 61
  • 1
  • 1
4

I think you can do this by calculating the height and width you want with javascript (via document.body.clientWidth etc.) and then injecting the iframe into your HTML like this:

var element = document.getElementById("myid");
element.innerHTML += "<iframe src='http://www.google.com' height='200' width='" + document.body.clientWidth * 0.8 + "'/>";

I didn't test this in IE6 but it seems to work with the good ones :)

Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92
  • 2
    Excuse my ignorance but wouldn't that make the iframe 80% of the source page, rather than zoom out the source page itself? – Phill Healey Nov 18 '14 at 16:40
3

For those of you having trouble getting this to work in IE, it is helpful to use -ms-zoom as suggested below and use the zoom function on the #wrap div, not the iframe id. In my experience, with the zoom function trying to scale the iframe div of #frame, it would scale the iframe size and not the content within it (which is what you're going for).

Looks like this. Works for me on IE8, Chrome and FF.

#wrap {
  overflow: hidden;
  position: relative;
  width:800px;
  height:850px;
  -ms-zoom: 0.75;
}
Tiago
  • 3,113
  • 2
  • 31
  • 45
3

This was my solution on a page with 890px width

#frame { 
overflow: hidden;
position: relative;
width:1044px;
height:1600px;
-ms-zoom: 0.85;
-moz-transform: scale(0.85);
-moz-transform-origin: 0px 0;
-o-transform: scale(0.85);
-o-transform-origin: 0 0;
-webkit-transform: scale(0.85);
-webkit-transform-origin: 0 0; 

}
Mathias Asberg
  • 3,562
  • 6
  • 30
  • 46
2

The #wrap #frame solution works fine, as long as the numbers in #wrap is #frame times the scale factor. It shows only that part of the scaled down frame. You can see it here scaling down websites and putting it into a pinterest like form (with the woodmark jQuery plugin):

http://www.genautica.com/sandbox/woodmark-index.html

Stefan Gruenwald
  • 2,582
  • 24
  • 30
2

So probably not the best solution, but seems to work OK.

<IFRAME ID=myframe SRC=.... ></IFRAME>

<SCRIPT>
    window.onload = function(){document.getElementById('myframe').contentWindow.document.body.style = 'zoom:50%;';};
</SCRIPT>

Obviously not trying to fix the parent, just adding the "zoom:50%" style to the body of the child with a bit of javascript.

Maybe could set the style of the "HTML" element, but didn't try that.

Graham
  • 53
  • 4
  • 1
    Don't do this. From https://developer.mozilla.org/en-US/docs/Web/CSS/zoom : "This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future." – hackel Aug 26 '16 at 16:21
  • +1 This (modifying the content of the iframe, not the iframe itself) seems like a better idea. I needed a way to scale down a page and show it as a preview of that page and this approach solved the problem. – akinuri Feb 22 '18 at 13:05
  • @akinuri Yes that's exactly what I used it for. I went through a number of solutions, but this seemed the easiest. I just iterated through the iframes and shrunk them all to get a page of thumbnails. No changes to the child pages are required. – Graham May 30 '20 at 09:31
  • Hello, sir. Your answer does not work if the src is a PDF. – Raul Chiarella May 25 '22 at 16:49
1

If your html is styled with css, you can probably link different style sheets for different sizes.

Jon
  • 253
  • 4
  • 9
0

I do not think HTML has such functionality. The only thing I can imagine would do the trick is to do some server-side processing. Perhaps you could get an image snapshot of the webpage you want to serve, scale it on the server and serve it to the client. This would be a non-interactive page however. (maybe an imagemap could have the link, but still.)

Another idea would be to have a server-side component that would alter the HTML. SOrt of like the firefox 2.0 zoom feature. this of course is not perfect zooming, but is better than nothing.

Other than that, I am out of ideas.

Alexandros Marinos
  • 1,396
  • 2
  • 15
  • 25
0

These solutions don't work properly for me (blur) with a Flexbox and an iFrame at 100% but if the Iframe uses the rem em or percent units then there is a solution that looks great:

  window.onload = function(){
    let ifElem = document.getElementById("iframe-id");
    ifElem.contentWindow.document.documentElement.style.fontSize="80%";
  }
Tofnet
  • 185
  • 2
  • 5
-3

As said, I doubt you can do it.
Maybe you can scale at least the text itself, by setting a style font-size: 80%;.
Untested, not sure it works, and won't resize boxes or images.

PhiLho
  • 40,535
  • 6
  • 96
  • 134