I have a meteor.js
app that functions as a news feed, with threads being posted and people commenting on the threads in realtime. This means that while you are looking at a post, there will be new comments being added to posts above and below and new threads will be added above. This will push the post you are focusing on down and out of the viewport, which is never expected (unless you're already scrolled to the top).
What is the best way to update the scrolling to maintain the same visual center as new content is added?
Approach: To prevent body scrolling but allow overlay scrolling we have to switch the overflow to be hidden when the overlay is being shown. And while the whole page's overflow is hidden or the scroll is disabled the overflow in the y-axis of the overlay is enabled and the overflow can be scrolled.
For touch devices, try adding a 1px wide, 101vh min-height transparent div in the wrapper of the overlay. Then add -webkit-overflow-scrolling:touch; overflow-y: auto; to the wrapper. This tricks mobile safari into thinking the overlay is scrollable, thus intercepting the touch event from the body.
To hide the scrollbar and disable scrolling, we can use the CSS overflow property. This property determines what to do with content that extends beyond the boundaries of its container. To prevent scrolling with this property, just apply the rule overflow: hidden to the body (for the entire page) or a container element.
You could try this approach:
scrollTop
value;Here's an example:
function randomString() {
return Math.random().toString(36).substring(7);
}
$('#addAbove').on('click', function(e){
var newDiv = $('<li class="post">' + randomString() + '</li>');
var savedScrollTop = $('#content').scrollTop();
$('#content').prepend(newDiv);
$('#content').scrollTop(savedScrollTop + newDiv.height());
});
$('#addBelow').on('click', function(e){
var newDiv = $('<li class="post">' + randomString() + '</li>');
$('#content').append(newDiv);
});
#content {
height: 100px;
overflow-y: scroll;
}
.post {
height: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="content">
<li class="post">u9tv190be29</li>
<li class="post">dgdr8gp66rp</li>
<li class="post">93vfntdquxr</li>
</ul>
<button id="addAbove">Add Above</button>
<button id="addBelow">Add Below</button>
Appending content below the current viewport shouldn't require adjustment.
Here's a blog post describing a similar approach, and a similar SO question.
I suggest you do like so, when a new item is to be added you check if you are at the top, if so, then just add the new item.
If not, you get the existing top/height of your item container, add the new item, get the item containers height a second time and then update the scroll top.
Here is a simple sample of how one can do, adding at both top and bottom (btw, at bottom don't need scroll compensation).
function addItem (totop) {
var msgdiv = document.getElementById('items');
var attop = scrollAtTop(msgdiv);
var prevtop = parseInt(msgdiv.scrollHeight - msgdiv.scrollTop);
if (totop) {
msgdiv.innerHTML = 'Long long content ' + (tempCounter++) + '!<br/>' + msgdiv.innerHTML;
if (!attop) {
updateScroll(msgdiv, parseInt(msgdiv.scrollHeight) - prevtop);
}
} else {
msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
}
}
var tempCounter = 10;
function updateScroll(el, top){
el.scrollTop = top;
}
function scrollAtTop(el){
return (el.scrollTop == 0);
}
html, body { height:100%; margin:0; padding:0; }
.items{
display: inline-block;
width: 300px;
height: 220px;
border: 1px solid black;
overflow: auto;
}
button { width: 15%; height: 44px; margin: 20px; vertical-align: top; }
<div class="items" id="items">
Long long content 9!<br/>
Long long content 8!<br/>
Long long content 7!<br/>
Long long content 6!<br/>
Long long content 5!<br/>
Long long content 4!<br/>
Long long content 3!<br/>
Long long content 2!<br/>
Long long content 1!<br/>
</div>
<button onclick="addItem(true);">Add 2 top</button><button onclick="addItem(false);">Add 2 bottom</button>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With