This should already work out-of-the-box based on the scroll anchoring spec currently implemented by Chrome and Firefox (link).
Directly from the spec introduction:
Today, users of the web are often distracted by content moving around
due to changes that occur outside the viewport. Examples include
script inserting an iframe containing an ad, or non-sized images
loading on a slow network.
[...]
Scroll anchoring attempts to keep the user’s view of the document
stable across layout changes. It works by selecting a DOM node (the
anchor node) whose movement is used to determine adjustments to the
scroll position.
It may not be working for you because the anchor node selected is not correct or you are using an unsupported browser (caniuse data). The exact process for the anchor node is described here. You can tweak the anchor selection algorithm by setting the CSS property overflow-anchor: none
on the nodes you want not to be the scroll anchor.
Working example for scroll anchoring: Just scroll within 5s and scroll up when the text turns red. You will see a new <p>
node added at the top.
const root = document.querySelector('#root');
const ol = document.querySelector('#list');
ol.las
setTimeout(() => {
const para = document.createElement('p');
para.innerText = 'A\nB\nC';
root.insertBefore(para, ol);
root.classList.add("red");
}, 3000);
.red {
color: red;
}
<div id="root">
<ol id="list">
<li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li><li>Hello</li><li>World!</li><li>Bye</li><li>World!</li>
</ol>
</div>
Can you share your code to see why it is not working?
.appendTo()
to move the elements into a div that is somehow not visible. Neither one seems a magic bullet to me (I see the obvious downsides to both), but throwing them out there FWIW in case something triggers a workable idea. – Sapsucker