如何设置<embed/object>嵌入HTML文档中<body>的scrollTop属性?
我来帮你拆解下这个问题,你遇到的核心是浏览器同源策略的安全限制,加上一开始找错了滚动控制的对象。下面一步步分析问题并给出可行方案:
为什么之前的尝试失败?
1. 最初用<embed>的问题
你尝试的document.getElementById("object").body.scrollTop = 0是错误的:<embed>元素本身没有body属性,内部加载的HTML文档需要通过contentDocument来访问。但即使你改成embed.contentDocument.body.scrollTop = 0,也会遇到和后来<object>一样的跨域问题——只要嵌入文档和主页面的源不一致(比如本地file://协议、不同域名/端口),浏览器就会阻止这种访问。
而你去掉.body后打印的scrollTop,是<embed>元素自身的滚动位置,不是内部文档的,所以它始终为0(因为嵌入的文档是在自己的文档上下文里滚动,不是<embed>元素本身)。
2. 换成<object>后的跨域错误
这个错误Blocked a frame with origin "null" from accessing a cross-origin frame是浏览器的同源策略在起作用:当两个页面的协议、域名、端口任意一个不同时,浏览器会禁止脚本跨域访问对方的文档对象。如果你是本地打开文件(用file://协议),浏览器会把源识别为null,嵌入的文档也属于null源,但部分浏览器对file://的同源限制更严格,依然会阻止访问。
可行的解决方案
根据你是否能控制嵌入的HTML文档,分两种情况处理:
情况1:你可以修改嵌入的HTML文档(或和主页面同源)
方案A:用postMessage跨上下文通信
这是跨域场景下最安全的解决方案,通过消息传递让嵌入文档自己执行回到顶部的操作:
- 主页面代码:给回到顶部按钮绑定点击事件,发送消息给嵌入文档
// 假设你的回到顶部按钮id是backToTopBtn document.getElementById('backToTopBtn').addEventListener('click', function() { const objectEl = document.getElementById('object'); // 发送消息,第二个参数尽量写具体的源(比如"http://your-domain.com"),*表示允许所有源,仅测试用 objectEl.contentWindow.postMessage('triggerScrollToTop', '*'); });
- 嵌入的HTML文档代码:添加消息监听,收到指令后执行滚动
window.addEventListener('message', function(event) { // 建议验证event.origin,只处理可信来源的消息 // if (event.origin === "http://your-trusted-domain.com") { if (event.data === 'triggerScrollToTop') { // 普通回到顶部 document.body.scrollTop = 0; // 或者平滑滚动(现代浏览器支持) // window.scrollTo({ top: 0, behavior: 'smooth' }); } // } });
方案B:启动本地服务器消除同源问题(仅本地开发用)
如果你是本地用file://打开文件导致的跨域问题,可以启动一个简单的本地HTTP服务器,让主页面和嵌入文档都通过http://localhost访问,这样就属于同源了:
- 用Python启动:
# Python 3 python -m http.server 8000 # Python 2 python -m SimpleHTTPServer 8000
- 然后在浏览器中访问
http://localhost:8000/你的主页面.html,此时再用你之前的代码:
var object = document.getElementById("object"); var htmlDocument = object.contentDocument; htmlDocument.body.scrollTop = 0; // 或者平滑滚动 htmlDocument.defaultView.scrollTo({top: 0, behavior: 'smooth'});
就能正常工作了。
情况2:你无法控制嵌入的HTML文档(且源不同)
这种情况下,浏览器的同源策略会完全阻止你操作嵌入文档的滚动,没有直接的解决办法。除非嵌入文档的服务器配置了CORS允许你的源访问,或者提供了官方的JS API来控制滚动——但这需要对方配合。
内容的提问来源于stack exchange,提问作者W.Tf

