如何禁止 iFrame 滚动其父级 window?
How do I forbid an iFrame from scrolling its parent window?
我有一个 HTML 文档,其底部包含一个 iframe。
在这种情况下,iframe 嵌入了一个 Google 电子表格,代码为:
<iframe id="gsheet-group" width="100%" height="400" src="https://docs.google.com/spreadsheets/d/<!----DOCUMENT_KEY----->/edit?usp=sharing&rm=minimal&gid=0&single=true&widget=false&chrome=false&headers=false">Loading sheet..</iframe>
我认为此 iframe 包含一些 javascript 会导致其在某些事件上 parent window to scroll to the top,例如加载完成或以特定方式导航其内容时。 (如果 iframe 嵌入到第二个 iframe 中,此行为仍然存在。)
如果我不能直接修改 iframe 的源代码,我可以防止父 window 在 iframe 嵌入的内容中被 javascript 操纵吗?
我试过的
感谢评论者的建议,none不幸解决了问题:
- 将
sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin"
添加到 <iframe>
元素(以删除 allow-top-navigation
;@CBroe)。
- 覆盖
window.scrollTo
(@Ryano)
- 将 iframe 放入单独的 iframe (@Ryano)
API 甚至 cross-origin iframe 都可以滚动顶部文档的 Element#scrollIntoView()
。我没有检查它是否真的是您的嵌入式页面在做什么,但这听起来像是一个非常合理的解释。
这是一个最小的例子。重现:
- 运行 片段
- 立即手动滚动到页面顶部。
- 等待大约 2 秒,让代码片段自动回滚查看:
(也可以在结果iframe中点击再次调用scrollIntoView,2s后)
onclick = e => setTimeout(() => {
document.body.scrollIntoView();
}, 2000);
onclick();
Scroll to the top of the top page and wait 2s.
在深入研究规范后,恐怕没有 out-of-the-box 解决方案来防止这种行为...
一件值得注意的事情是 Chrome will not scroll to fixed elements in an iframe。这意味着我们实际上可以 hack-around 这个 bug 来定义一个“scroll-stop”层:你可以将目标 iframe 包裹在另一个 iframe 中,设置这个内部 iframe 的位置固定,以便它完全覆盖包装 iframe。这将阻止 Chrome 滚动此 iframe 的祖先:
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>
然而这是一个完整的hack-around,它基本上是一个漏洞利用,显然在其他web-browsers中不起作用,甚至可能在Chrome的未来版本中失败,如果他们解决了问题。
但这是我目前唯一能找到的东西。
不过,我邀请您做的是在 W3C's CSS working group's Github repo 上提出您的观点,以便他们考虑添加一个 属性 以正式允许此功能。
在遵循@Kaiido 的建议在 W3C 跟进之后,那里的评论确认当前标准确实不支持所需的行为。如果接受,proposal 将允许通过以下方式禁用垂直滚动:
<iframe src="..." allow="vertical-scroll 'none'"></iframe>
可以跟踪提案的状态here。
我有一个 HTML 文档,其底部包含一个 iframe。
在这种情况下,iframe 嵌入了一个 Google 电子表格,代码为:
<iframe id="gsheet-group" width="100%" height="400" src="https://docs.google.com/spreadsheets/d/<!----DOCUMENT_KEY----->/edit?usp=sharing&rm=minimal&gid=0&single=true&widget=false&chrome=false&headers=false">Loading sheet..</iframe>
我认为此 iframe 包含一些 javascript 会导致其在某些事件上 parent window to scroll to the top,例如加载完成或以特定方式导航其内容时。 (如果 iframe 嵌入到第二个 iframe 中,此行为仍然存在。)
如果我不能直接修改 iframe 的源代码,我可以防止父 window 在 iframe 嵌入的内容中被 javascript 操纵吗?
我试过的
感谢评论者的建议,none不幸解决了问题:
- 将
sandbox="allow-scripts allow-forms allow-pointer-lock allow-same-origin"
添加到<iframe>
元素(以删除allow-top-navigation
;@CBroe)。 - 覆盖
window.scrollTo
(@Ryano) - 将 iframe 放入单独的 iframe (@Ryano)
API 甚至 cross-origin iframe 都可以滚动顶部文档的 Element#scrollIntoView()
。我没有检查它是否真的是您的嵌入式页面在做什么,但这听起来像是一个非常合理的解释。
这是一个最小的例子。重现:
- 运行 片段
- 立即手动滚动到页面顶部。
- 等待大约 2 秒,让代码片段自动回滚查看:
(也可以在结果iframe中点击再次调用scrollIntoView,2s后)
onclick = e => setTimeout(() => {
document.body.scrollIntoView();
}, 2000);
onclick();
Scroll to the top of the top page and wait 2s.
在深入研究规范后,恐怕没有 out-of-the-box 解决方案来防止这种行为...
一件值得注意的事情是 Chrome will not scroll to fixed elements in an iframe。这意味着我们实际上可以 hack-around 这个 bug 来定义一个“scroll-stop”层:你可以将目标 iframe 包裹在另一个 iframe 中,设置这个内部 iframe 的位置固定,以便它完全覆盖包装 iframe。这将阻止 Chrome 滚动此 iframe 的祖先:
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>
然而这是一个完整的hack-around,它基本上是一个漏洞利用,显然在其他web-browsers中不起作用,甚至可能在Chrome的未来版本中失败,如果他们解决了问题。
但这是我目前唯一能找到的东西。
不过,我邀请您做的是在 W3C's CSS working group's Github repo 上提出您的观点,以便他们考虑添加一个 属性 以正式允许此功能。
在遵循@Kaiido 的建议在 W3C 跟进之后,那里的评论确认当前标准确实不支持所需的行为。如果接受,proposal 将允许通过以下方式禁用垂直滚动:
<iframe src="..." allow="vertical-scroll 'none'"></iframe>
可以跟踪提案的状态here。