Wednesday 15 January 2020

Maintaining scroll position only works when not near the bottom of messages div

I'm trying to mimic other mobile chatting apps where when you select the send-message textbox and it opens the virtual keyboard, the bottom-most message is still in view. There doesn't seem to be a way to do this with CSS amazingly, so JavaScript resize (only way to find out when the keyboard is opened and closed apparently) events and manual scrolling to the rescue.

Someone provided this solution and I found out this solution, which both seem to work.

Except in one case. For some reason, if you are within MOBILE_KEYBOARD_HEIGHT (250 pixels in my case) pixels of the bottom of the messages div, when you close the mobile keyboard, something strange happens. With the former solution, it scrolls to the bottom. And with my solution, it instead scrolls up MOBILE_KEYBOARD_HEIGHT pixels from the bottom.

If you are scrolled above this height, both solutions provided above work flawlessly. It's only when you are near the bottom that they have this minor issue.

I thought maybe it was just my program causing this with some weird stray code, but no, I even reproduced a fiddle and it has this exact issue. My apologies for making this so difficult to debug, but if you go to https://jsfiddle.net/t596hy8d/6/show (the show suffix provides a full-screen mode) on your phone, you should be able to see the same behavior.

That behavior being, if you scroll up enough, opening and closing the keyboard maintains the position. However, if you close the keyboard within MOBILE_KEYBOARD_HEIGHT pixels of the bottom, you'll find that it scrolls to the bottom instead.

What is causing this?

Code reproduction here:

window.onload = function(e){ 
  document.querySelector(".messages").scrollTop = 10000;
  
  bottomScroller(document.querySelector(".messages"));
}
  

function bottomScroller(scroller) {
  let scrollBottom = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;

  scroller.addEventListener('scroll', () => { 
  scrollBottom = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;
  });   

  window.addEventListener('resize', () => { 
  scroller.scrollTop = scroller.scrollHeight - scrollBottom - scroller.clientHeight;

  scrollBottom = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;
  });
}
.container {
  width: 400px;
  height: 87vh;
  border: 1px solid #333;
  display: flex;
  flex-direction: column;
}

.messages {
  overflow-y: auto;
  height: 100%;
}

.send-message {
  width: 100%;
  display: flex;
  flex-direction: column;
}
<div class="container">
  <div class="messages">
  <div class="message">hello 1</div>
  <div class="message">hello 2</div>
  <div class="message">hello 3</div>
  <div class="message">hello 4</div>
  <div class="message">hello 5</div>
  <div class="message">hello 6 </div>
  <div class="message">hello 7</div>
  <div class="message">hello 8</div>
  <div class="message">hello 9</div>
  <div class="message">hello 10</div>
  <div class="message">hello 11</div>
  <div class="message">hello 12</div>
  <div class="message">hello 13</div>
  <div class="message">hello 14</div>
  <div class="message">hello 15</div>
  <div class="message">hello 16</div>
  <div class="message">hello 17</div>
  <div class="message">hello 18</div>
  <div class="message">hello 19</div>
  <div class="message">hello 20</div>
  <div class="message">hello 21</div>
  <div class="message">hello 22</div>
  <div class="message">hello 23</div>
  <div class="message">hello 24</div>
  <div class="message">hello 25</div>
  <div class="message">hello 26</div>
  <div class="message">hello 27</div>
  <div class="message">hello 28</div>
  <div class="message">hello 29</div>
  <div class="message">hello 30</div>
  <div class="message">hello 31</div>
  <div class="message">hello 32</div>
  <div class="message">hello 33</div>
  <div class="message">hello 34</div>
  <div class="message">hello 35</div>
  <div class="message">hello 36</div>
  <div class="message">hello 37</div>
  <div class="message">hello 38</div>
  <div class="message">hello 39</div>
  </div>
  <div class="send-message">
        <input />
  </div>
</div>


from Maintaining scroll position only works when not near the bottom of messages div

No comments:

Post a Comment