Ben Lachman Ben Lachman - 3 months ago 7
CSS Question

Preserving scroll position while inserting div, but only when user has scrolled

I have a container

div
that is used for displaying log messages. I prepend each message as a separate child
div
element when it is generated. The parent
div
is set to
overlay-y:auto
such that after the message elements exceed the height of the parent container, it scrolls. The behavior I'm trying to produce is that messages scroll as normal, except that if the user scrolls down through the "history" of the messages they don't scroll/move out of the visible area of the parent
div
when new messages are prepended to the top of the message list.

My current attempt looks like this:

html:

<div id='log'>
<h4>Log</h4>
<div id='log-rows'></div>
</div>


js:

log: function(text) {
var messageHTML = "<div><span class='timestamp'>" + (new Date()).toISOString() + "</span> - <span class='message'>" + text + "</span></div>";

this.$el.find("#log-rows").prepend(messageHTML);

var firstLogMessage = $('#log-rows').children().first();

$('#log-rows').children().each( function(index, row) {
row.scrollTop += firstLogMessage.height();
});

...
}


css:

#log-rows {
max-height: 250px;
overflow-y: auto;
}

Answer

Edit your log function. This works for me:

function log(text) {
  var messageHTML = "<div><span class='timestamp'>" + (new Date()).toISOString() + "</span> - <span class='message'>" + text + "</span></div>";

  $("#log").find("#log-rows").prepend(messageHTML);

  var scrollTop = $("#log-rows").scrollTop();

  if (scrollTop > 0) {
    var childHeight = $("#log-rows div").outerHeight(true); // get's the new element's full height including margin
    var scrollDelta =  scrollTop + childHeight;
    $("#log-rows").scrollTop(scrollDelta);
  }
}
Comments