I have an HTML document which, towards its bottom, contains an iframe.
In this case, the iframe embeds a Google Spreadsheet, with the code:
<iframe id="gsheet-group" width="100%" height="400" src="/<!----DOCUMENT_KEY----->/edit?usp=sharing&rm=minimal&gid=0&single=true&widget=false&chrome=false&headers=false">Loading sheet..</iframe>
I believe that this iframe contains some javascript that causes its parent window to scroll to the top on certain events, such as when its loading is plete or its content is navigated in certain ways. (This behaviour persists if the iframe is embedded within a second iframe.)
If I can't directly modify the source code of the iframe, can I prevent a parent window from being manipulated by javascript in iframe-embedded content?
What I've tried
I'm grateful to the menters for suggestions, none of which have sadly solved the problem:
- Adding
sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin"
to the<iframe>
element (to removeallow-top-navigation
; @CBroe). - Overriding
window.scrollTo
(@Ryano) - Putting the iframe in a separate iframe (@Ryano)
I have an HTML document which, towards its bottom, contains an iframe.
In this case, the iframe embeds a Google Spreadsheet, with the code:
<iframe id="gsheet-group" width="100%" height="400" src="https://docs.google./spreadsheets/d/<!----DOCUMENT_KEY----->/edit?usp=sharing&rm=minimal&gid=0&single=true&widget=false&chrome=false&headers=false">Loading sheet..</iframe>
I believe that this iframe contains some javascript that causes its parent window to scroll to the top on certain events, such as when its loading is plete or its content is navigated in certain ways. (This behaviour persists if the iframe is embedded within a second iframe.)
If I can't directly modify the source code of the iframe, can I prevent a parent window from being manipulated by javascript in iframe-embedded content?
What I've tried
I'm grateful to the menters for suggestions, none of which have sadly solved the problem:
- Adding
sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin"
to the<iframe>
element (to removeallow-top-navigation
; @CBroe). - Overriding
window.scrollTo
(@Ryano) - Putting the iframe in a separate iframe (@Ryano)
- "this iframe contains some javascript ..." Remove the script? – Teemu Commented Feb 1, 2022 at 12:43
- I don't think it's possible to edit the content of an iframe? – Martin Smith Commented Feb 1, 2022 at 12:44
-
1
Is it manipulating the URL hash of the parent document maybe ...? That could cause a "jump", or also smooth scrolling if the parent page had the latter enabled - and is not restricted by the Same Origin Policy, write access to the parent's location is allowed. In that case, sandboxing the iframe to remove
allow-top-navigation
might help. – C3roe Commented Feb 1, 2022 at 13:15 - 1 i agree with @Cbroe, and if that doesn't work maybe try overriding window.scrollTo on your page? or add some css to make your page not scrollable? or get really dirty and put the iframe inside another iframe? whatever fits :) – Ryano Commented Feb 1, 2022 at 14:11
- 2 No time to check right now, but IIRC scrollIntoView will make your parent page scroll even when called from inside a cross-origin iframe. Not sure how you could prevent that. – Kaiido Commented Mar 10, 2022 at 9:00
2 Answers
Reset to default 3One such API that would allow even cross-origin iframes to scroll the top document is Element#scrollIntoView()
. I didn't check it's really what your embedded page was doing, but that sounds like a very plausible explanation.
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:
(You can also click in the result iframe to call scrollIntoView again, 2s later).
onclick = e => setTimeout(() => {
document.body.scrollIntoView();
}, 2000);
onclick();
Scroll to the top of the top page and wait 2s.
After digging the specs I'm afraid there is no out-of-the-box solution to prevent this behavior...
One noticeable thing though is that Chrome will not scroll to fixed elements in an iframe. This means that we can actually hack-around this bug to define a "scroll-stop" layer: You can wrap the target iframe in an other iframe, set this inner iframe's position to fixed and so that it covers entirely the wrapping iframe. This will prevent Chrome from scrolling this iframe's ancestors:
iframe { position: fixed; top: 0; width: 100vw; height: 100vh; border: none; padding: 0; margin: 0; }
<iframe srcdoc="
<script>
onclick = e => setTimeout(() => {
document.querySelector('h1').scrollIntoView();
}, 2000);
onclick();
</script>
<h1 style='margin-top: 100vh' >I still scroll into view, but not the top page.</h1>
"></iframe>
However this is a plete hack-around, it's basically a bug exploit, it obviously doesn't work in other web-browsers and it may even fail in a future version of Chrome, if they fix the issue.
But that's the only thing I could find for now.
What I invite you to do though is to make your point over at W3C's CSS working group's Github repo so that they consider adding a property that would allow this feature officially.
After following @Kaiido's advice to follow this up at W3C, ments there have confirmed that the desired behaviour is indeed not supported by current standards. If accepted, a proposal will allow vertical scrolling to be disabled via:
<iframe src="..." allow="vertical-scroll 'none'"></iframe>
The status of the proposal can be tracked here.