Here's some code showing document.documentElement.scrollTop
as you scroll
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);
#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);
}
<div id="under"></div>
<div id="content"></div>
<pre id="debug"></pre>
And here is the exact same code running in an iframe.
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'}));
<iframe></iframe>
Inside the iframe, the value document.documentElement.scrollTop
never changes. Why? Note: Tested on Chrome, Firefox, and Safari
CodePudding user response:
The issue is not related to iframe
, as you may note your working example also runs in an iframe. It is about the content of the iframe, specifically the document quirks. You may note the following warning in the console when the iframe is loaded:
This page is in Quirks Mode. Page layout may be impacted. For Standards Mode use “<!DOCTYPE html>”.
Thus, the scrollTop
in this case behaves according to the following rule of the specs:
- If the element is the root element and document is in quirks mode, return zero and terminate these steps.
To make it work, the html
must be formatted with the proper DOCTYPE
:
const script = 'script';
const html = `
<!DOCTYPE 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'}));
<iframe></iframe>
CodePudding user response:
It seems that documentElement.scrollTop: \${document.body.scrollTop}
works better in that case, thanks to this answer discussion.
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.body.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'}));
<iframe></iframe>