iframe-resizer icon indicating copy to clipboard operation
iframe-resizer copied to clipboard

Width downsizing not working

Open zxti opened this issue 6 years ago • 13 comments

How do you prevent the iframe from growing unbounded? It seems easy to cause this problem, especially with width but also with height. Below is a simple minimal example - pressing 'go' toggles on/off a div appearing far to the right, but once it appears, the width never reverts back to its original size.

I think this is because of the following feedback loop:

  • divs are width:100% of the parent document body whose width is 100% of the iframe.
  • iFrameResizer makes the iframe width in turn determined by the document contents.

I'm hoping there's a way to match the behavior in a normal iframe or viewport, where there's a "viewport size" that the document body width reverts to once it's no longer propped wider by the .c div. (Of course, without actually clipping the content to that "viewport size.") Am I making sense? Is there a way to accomplish this?

index.html:

<script src="iframeResizer.min.js"></script>
<iframe src="child.html" scrolling="no"></iframe>
<script>
  iFrameResize({ sizeWidth: true }, document.querySelector("iframe"));
</script>

child.html:

<!DOCTYPE html>
<html>
  <body>
    <script src="iframeResizer.contentWindow.min.js"></script>
    <script>
      function go() {
        if (document.querySelector(".c").style.display === "block") {
          document.querySelector(".c").style.display = "none";
        } else {
          document.querySelector(".c").style.display = "block";
        }
      }
    </script>
    <button onclick="go()">go</button>
    <div
      class="c"
      style="height: 50px; width:10px; left: 500px; position: absolute; display: none; background: black;"
    >
      hello
    </div>
    <div style="height: 500px; width:100%; background: silver;">hello</div>
  </body>
</html>

(I'd be happy to move this into a jsfiddle or codepen, but I wasn't sure how to get iframes to work in them.)

zxti avatar Feb 11 '19 01:02 zxti

You need to make sure your css, is not sized. To be greater than tha visable page size.

You might also try playing with taggedElement resize method to control which element is used to size the view port

davidjbradshaw avatar Feb 11 '19 10:02 davidjbradshaw

I'd like to present some deeper motivation:

  1. The "visible page size" is highly uncontrollable (e.g. what device the user is using, how large their viewport is, their zoom level, etc.)

  2. It is routine for a page to overflow vertically and horizontally. Particularly vertically (any time you can scroll down on a page), but also horizontally (e.g. a sideways-scrolling gallery or carousel) and also both simultaneously.

With a normal iframe (without enabling iframeResizer), this is what happens with the above code example:

  1. Initially, iframe is its default of 300px wide.

  2. Press go to make a div appear at 500px, causing a horizontal scrollbar to appear. The document is now >500px wide.

  3. Press go again to remove the div. The horizontal scrollbar disappears, and the document is now back to being 300px wide.

So my question/issue was around how to make iframeResizer behave similarly—I want to be able to specify a "viewport width" (say 300px) such that when there is no longer content stretching the document width, the iframe shrinks back down to the viewport width. Is this possible?

I tried modifying child.html so that the html root element had a fixed width of 300px, so that all the content on the page was within 300px, but still the iframe does not downsize.

<html style='width:300px;background:black'>
...

I played with taggedElement. Is there a particular pattern of usage that would help with this?

Thanks.

zxti avatar Feb 14 '19 08:02 zxti

I also tried modifying child.html so that the html root element had a fixed width of 300px, so that all the content on the page was within 300px, but still the iframe does not downsize.

<html style='width:300px;background:black'>
...

zxti avatar Feb 14 '19 08:02 zxti

Use max-width not width.

davidjbradshaw avatar Feb 14 '19 09:02 davidjbradshaw

I tried max-width, but there seems to be no difference.

zxti avatar Feb 15 '19 00:02 zxti

I would suggest asking on StackOverflow then. This is an issue with your CSS rather than this library

davidjbradshaw avatar Feb 15 '19 08:02 davidjbradshaw

This isn't a CSS issue, it's a very simple example. The issue is the difference between using a normal iframe vs using this library. With a normal iframe, the document changes from 300px to 500px then back to 300px. With the library, once at 500px it stays at 500px, even though nothing in the document is propping it open at 500px.

zxti avatar Feb 15 '19 23:02 zxti

I think there is a bug here. But it can be worked around with widthCalculationMethod: 'taggedElement' and data-iframe-width.

Here's a demo, with 5 different iframes in different stages. https://fun.unslumping.org/meta/static/example/fat_iframe.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Fat iframe demo</title>
</head>
<body>

1<iframe src="fat_iframe_content.html" id="iframe1" allowfullscreen="allowfullscreen">'></iframe>
2<iframe src="fat_iframe_content.html" id="iframe2" allowfullscreen="allowfullscreen"> ></iframe>
3<iframe src="fat_iframe_content.html" id="iframe3" allowfullscreen="allowfullscreen"> ></iframe>
4<iframe src="fat_iframe_content.html" id="iframe4" allowfullscreen="allowfullscreen"> ></iframe>
5<iframe src="fat_iframe_content.html" id="iframe5" allowfullscreen="allowfullscreen"> ></iframe>

<script src="/meta/static/code/iframeResizer.min.js"></script>
<script>
iFrameResize({log:true},                                                              '#iframe2');
iFrameResize({log:true, sizeWidth: true},                                             '#iframe3');
iFrameResize({log:true, sizeWidth: true, widthCalculationMethod: 'rightMostElement'}, '#iframe4');
iFrameResize({log:true, sizeWidth: true, widthCalculationMethod: 'taggedElement'},    '#iframe5');
</script>
</body>
</html>

To reproduce:

  • Full-screen each video, then escape it. (Either double-click each video, or start and stop it to make the full-screen widget appear.)
  • You'll see frames 3 and 4 come back very wide, as wide as your screen. I suggest this is a bug. It doesn't happen with sizeHeight.

Screenshot 2019-08-18 20 35 44

The iframe content backgrounds are silver so you can see them. See how frames 3 & 4 are wider than the browser window?

The five frames:

  1. No resizing, recovers from full-screen.
  2. Default resizing. sizeHeight is enabled, and can be seen to work. Recovers from full-screen.
  3. Introduce sizeWidth. This will not downsize after full-screen.
  4. Try rightMostElement. It doesn't help.
  5. taggedElement fixes it. But you need to make sure the iframe content elements have data-iframe-width='x' attributes. (The attribute value doesn't seem to matter.) Otherwise the iframes will downsize to wafer-thin oblivion.

The frame contents are identical:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Fat iframe content demo</title>
</head>
<body style="background-color: silver;">
    <iframe src="https://www.youtube.com/embed/o9tDO3HK20Q?feature=oembed"
            allowfullscreen="allowfullscreen" data-iframe-width="300"></iframe>
    <script src="/meta/static/code/iframeResizer.contentWindow.min.js"></script>
</body>
</html>

And yes, DOCTYPE is required.

This behaves the same way on all of the following browsers. In every case, taggedElement is the only way a sizeWidth iframe can downsize after full-screen.

  • Chrome 76
  • Firefox 68
  • Microsoft Edge 78
  • Internet Explorer 11
  • Opera 62

One curious thing, if you resize the window repeatedly, frame4 will gradually downsize to the right size. This weird effect can be seen on all these browsers.

I tried and tried and finally gave up getting a demo on jsbin or jsfiddle. Security was an obstacle. And jsbin wanting money was an obstacle. So these are hosted on my own domain.

The application that sent me down this happy trail was this innocent remark in the oembed Security section:

To avoid [XSS attacks], it is recommended that consumers display the HTML in an iframe, hosted from another domain.

BobStein avatar Aug 19 '19 01:08 BobStein

Thanks for all the research on that. Not sure why the other methods are failing here. TaggedElement has always been the most robust and you don’t need to add a value to it, just the attribute is enough.

davidjbradshaw avatar Aug 20 '19 14:08 davidjbradshaw

Thank you for iframe-resizer. It was dreamy how well it worked on the first try.

BobStein avatar Aug 20 '19 14:08 BobStein

I just had this same issue with the iframe height not downsizing, and it turned out to be CSS on the child content. The body element had height: 100% applied to it. Once I set that to auto, the downsizing worked.

tkawai21 avatar Jan 13 '20 17:01 tkawai21

@tkawai21 yep this almost always a CSS issue, but can be had to spot sometimes

davidjbradshaw avatar Jan 13 '20 20:01 davidjbradshaw

I just had this same issue with the iframe height not downsizing, and it turned out to be CSS on the child content. The body element had height: 100% applied to it. Once I set that to auto, the downsizing worked.

In most cases (and in mine) you don't have control over the HTML/CSS in the iframe. My iframes have, annoyingly, html's "width" and "height" set to 100%... so the height downsizing NEVER works... and I can't find a workaround. :(

exzizt avatar Feb 09 '20 19:02 exzizt