JavaScript Resize Observer: Resize on the inside of an element (iframe)

647 Views Asked by At

I am looking for a way to detect changes to the scrollWidth of an iframe using a resize observer.

It seems that by default the observer only observes changes to the content box, like in the following example, where a resize from the outside is detected, but a resize from the inside is not.

const iframe = document.querySelector('iframe');

// Add some content to the iframe

const content = `<button style="width: 100px; height: 100px; background-color: grey;" onclick="this.style.width = this.style.width == '500px' ? '' : '500px';">Click to resize the iframe from the inside</button>`;
const blob = new Blob([content], {type: 'text/html'});
iframe.src = URL.createObjectURL(blob);

// Button event

document.querySelector('button').addEventListener('click', () => {

  iframe.style.width = iframe.style.width == '200px' ? '' : '200px';

});

// ----------------- Question starts here -----------------

const resizeObserver = new ResizeObserver(() => {

  console.log('Resized!');

});

resizeObserver.observe(iframe);
iframe{
  width: 120px;
  height: 120px;
}
<iframe src="#"></iframe>
<button>Click to resize the iframe from the outside!</button>

The resize observer works great when the iframe itself gets resized, but not when the contents resize. I don't think this problem is unique to iframes, but to the resize observer in general.

A possible solution would be to attach a mutation observer to the body of the iframe and monitor the entire child tree or to check for changes using setInterval. However, I am looking for a more performant solution. Preferably using an observer on a single element or an event listener.

If anyone knows of a good solution to monitor for both changes (to the width inside the iframe and outside of it) or has some general ideas it would be greatly appreciated.

1

There are 1 best solutions below

1
On

I wrote a library called iframe-resizer and a large part of the code is working this out. You might find it helpful to look at all the different ways it detects events that cause the content of an iframe to resize and then calculate the new size.

I have found that placing MutationObserver on every element of a page has no real impact on performance. But it also doesn’t detect everything that might trigger the content to resize. For example a user resizing a textarea input does not mutate the DOM.

If all your are interested in is scrollWidth then the simplest solution would be to use requestAnimationFrame to poll the value and see if it has changed every time the page is redrawn.

You also need to be careful with CSS, as it is possible to overflow the document element if you’re not careful. I find it is more reliable to tag an element at the bottom of the page and track it’s location to be more reliable.