Prevent a cross-origin iframe from scrolling its parentEN
lang
EN
date
Aug 19, 2022
Property
slug
iframe-scroll
status
Published
tags
JavaScript
summary
Accidentally found in business work that after embedding some specific iframes, the top-level page will automatically scroll to the iframe, at the the time when iframe is loaded.
type
Post
Accidentally found in business work that after embedding some specific iframes, the top-level page will automatically scroll to the iframe, at the the time when iframe is loaded.
How to reproduce
Here is a minimal example. To reproduce:
- Run the snippet
- Immediately scroll to the top of the page manually.
- Wait about 2s for the snippet scrolls back to view automagically:
Code Snippet
onclick = e => setTimeout(() => { document.body.scrollIntoView(); }, 2000); onclick();
Main reason
One such API that would allow even cross-origin iframes to scroll the top document is
Element#scrollIntoView()
.Solutions
Stop the scroll behavior
position:fixed
an iframe, cause Chrome will not scroll to fixed elements in an iframe
fixed the iframe based on the top window
fixed the iframe to specific element using css transform
css transoform can make element have viewport like behavior.
But it didn’t work!!!
Here is the code for this example.
<div className="wrapper"> <div className="force-viewport"> <iframe src={url} frameBorder="0" ></iframe> </div> </div>
.wrapper { transform: translateZ(0); .force-viewport { overflow: hidden; height: 800px; iframe { position: fixed; inset: 0; } } }
Reduce auto-scroll impact
display: none
an iframe
Set the iframe style to display:none, then recover the style after loaded, timeout is needed if the page took a long time to load.
Similar to the example above, but with the iframe position check (whether the iframe is inside viewport)
Best Practice
<LoadingWrapper loading={frameLoading}> <InViewWrapper keepDOM initHeight={800}> <iframe src={frameUrl} frameBorder="0" onLoad={() => setFrameLoading(true)} sandbox="allow-scripts allow-forms allow-same-origin" ></iframe> </InViewWrapper> </LoadingWrapper>
Element.scrollIntoView
polyfillshttps://github.com/stipsan/scroll-into-view-if-needed