为何iframe中document.documentElement.scrollTop停止更新?
问题:iframe中
document.documentElement.scrollTop值始终不变的原因 普通页面代码(展示滚动时的document.documentElement.scrollTop值)
JavaScript
const contentElem = document.querySelector('#content') for (let i = 0; i < 500; ++i) { const elem = document.createElement('h1'); elem.textContent = `line: ${i}`; contentElem.appendChild(elem); } const debugElem = document.querySelector('#debug'); function update() { debugElem.textContent = `scrollY: ${window.scrollY} documentElement.scrollTop: ${document.documentElement.scrollTop} documentElement.nodeName: ${document.documentElement.nodeName}`; requestAnimationFrame(update); } requestAnimationFrame(update);
CSS
#under { position: absolute; transform: translateY(500px); left: 0; top: 0; background-color: pink; width: 100%; height: 100%; z-index: -1; } #debug { position: fixed; color: white; left: 0; top: 0; background-color: rgba(0, 0, 0, 0.8); }
HTML
<div id="under"></div> <div id="content"></div> <pre id="debug"></pre>
iframe中运行的代码
JavaScript
const script = 'script'; const html = ` <style> #under { position: absolute; transform: translateY(500px); left: 0; top: 0; background-color: pink; width: 100%; height: 100%; z-index: -1; } #debug { position: fixed; color: white; left: 0; top: 0; background-color: rgba(0, 0, 0, 0.8); } </style> <div id="under"></div> <div id="content"></div> <pre id="debug"></pre> <${script}> const contentElem = document.querySelector('#content') for (let i = 0; i < 500; ++i) { const elem = document.createElement('h1'); elem.textContent = \`line: \${i}\`; contentElem.appendChild(elem); } const debugElem = document.querySelector('#debug'); function update() { debugElem.textContent = \`scrollY: \${window.scrollY} documentElement.scrollTop: \${document.documentElement.scrollTop} documentElement.nodeName: \${document.documentElement.nodeName}\`; requestAnimationFrame(update); } requestAnimationFrame(update); </${script}> `; const iframeElem = document.querySelector('iframe'); iframeElem.src = URL.createObjectURL(new Blob([html], {type: 'text/html'}));
HTML
<iframe></iframe>
原因分析
核心原因是iframe内的文档进入了怪异模式(Quirks Mode):
- 你生成的iframe内容没有声明
<!DOCTYPE html>,浏览器会切换到怪异模式渲染。 - 在怪异模式下,页面的滚动容器是
<body>元素而非<html>元素,因此document.documentElement.scrollTop始终保持0,而document.body.scrollTop才会随滚动变化。 window.scrollY能正常返回滚动值,是因为这个API是全局视口级别的,直接返回当前页面的滚动偏移,不受滚动容器的影响。
修复方法
在iframe的HTML内容开头添加标准DOCTYPE声明,强制浏览器进入标准模式:
<!DOCTYPE html>
添加后,document.documentElement.scrollTop就会随滚动正常更新了。
内容的提问来源于stack exchange,提问作者user128511
相关产品推荐
相关产品推荐

