0

General Info
Working on a chatsystem. When users join a chatroom, they're unable to see any previous messages. I'm trying to make the first new message appear at the bottom of the messages container and then just append followup messages underneath it.

Ideas I've had myself

  1. Make the container relative and each message absolute positioned. Then just give the message bottom: 10px;. This wouldn't work, as it would keep the messages at the bottom and start stacking them up.

  2. Create an invisible div inside the container with a percentage height so most of the empty space is taken and any message appended would appear underneath it. This also wouldn't work because percentage height would remain in effect and keep pushing everything down.

  3. Create an invisible div and use Javascript to give it a static height based on the users screensize. It would work, but issues will arise if the user resizes his screen. Could technically solve that with a custom event handler onresize and resize the invisible div, but it feels like this would be a wrong approach to the issue.

Code

Chatroom messages container:

<div class="chatroom" id="room-roomname"></div>

Example of a message:

<div class="row">
    <div class="col s12 chat-msg-container">
        <div class="chat-msg">
            <span class="default-color">
                Username
            </span><br/>
            <span>
                Message
            </span>
        </div>
        <div class="chat-msg-image">
            <img class="userImg" src="">
        </div>
    </div>
</div>

Question
I'm looking for the correct approach to do this. How to append a div at the visual bottom of a div?

icecub
  • 8,615
  • 6
  • 41
  • 70
  • Possible duplicate of [How can I position my div at the bottom of its container?](https://stackoverflow.com/questions/526035/how-can-i-position-my-div-at-the-bottom-of-its-container) – Nick Dec 01 '18 at 01:00
  • @Nick It's not a duplicate. If you look at idea 1, that solution wouldn't work for me. Absolute positioning a div would force it to stay at that position. – icecub Dec 01 '18 at 01:01
  • I agree about answer 1. But my first inclination on reading your question was to use a table cell, and answer 2 details how to do that. Also answer 3 seems good for modern browsers. – Nick Dec 01 '18 at 01:03
  • @Nick I agree it might be in the right direction. I'm afraid it wouldn't work in my situation though. The message is supposed to appear at the bottom, but start moving up after that. If a second message is appended, it shouldn't appear "above" the first message. It's like the first message starts at the bottom, but doesn't stay there afterwards. Kinda hard to explain.. – icecub Dec 01 '18 at 01:07
  • I understand - but as long as you append the second message to the first, it should move up automatically? Possibly the biggest issue you will have to deal with is overflow at the top of the div... – Nick Dec 01 '18 at 01:09
  • @Nick Well I guess there's only one way to find out and that's actually trying it out. I'll let you know if that solution works and accept the dupe if it does. Thanks for helping so far :) – icecub Dec 01 '18 at 01:11
  • @Nick As I suspected it didn't work. The messages wouldn't appear at the bottom. However, Nick Parsons's solution worked perfectly. Unfortunetely he deleted his answer. Would've accepted it.. – icecub Dec 01 '18 at 01:45
  • 1
    I'll vote to undelete... – Nick Dec 01 '18 at 01:48

1 Answers1

1

Using translateY with fixed whole msg container:

var msgRow = `<div class="row">
    <div class="col s12 chat-msg-container">
        <div class="chat-msg">
            <span class="default-color">
                Username
            </span><br/>
            <span>
                Message {{num}}
            </span>
        </div>
        <div class="chat-msg-image">
            <img class="userImg" src="">
        </div>
    </div>
</div>
`;

var scrollbox = document.getElementById('scroll-box');
var chatrooms = document.querySelectorAll('.chatroom');
var chatbox = document.getElementById('chat');

var i = 0;
var id = setInterval(function() {
  let room = chatrooms[i % 2];
  room.innerHTML += msgRow.replace('{{num}}', i);
  if (i == 0 || i == 1) room.classList.add('active');
  if (i == 3) window.clearInterval(id);
  i++;
}, 1000);
#chatrooms {
  position: absolute;
  top: 0;
  left:0;
  width: 100%;
  border: 1px solid red;
  overflow: hidden;
}

#scroll-box {
  height: 170px;
  overflow-y: scroll;
  display: flex;
}

#chat.container {
  margin-top: auto;
}

.chatroom {
  align-self: flex-end;
  transform:translateY(100%);
  transition: transform 0.5s ease-in;
}

.chatroom.active {
  transform: translateY(0%);
}

.chat-msg-container {
  background-color: lightgrey;
  margin-bottom: 10px;
  animation: animateElement ease-in .5s;
  animation-iteration-count: 1;
}

@keyframes animateElement{
  0% {
    transform:  translateY(100%);
  }
  100% {
    transform:  translateY(0%);
  }
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>

<div id="chatrooms">
  <div id="scroll-box">
    <div id="chat" class="container">
      <div class="row">
        <div class="chatroom col-6"></div>
        <div class="chatroom col-6"></div>
      </div>
    </div>
  </div>
</div>
bigless
  • 2,849
  • 19
  • 31
  • I actually really like the transition effect you've put in there. I'm gonna see if I can work this out in my system. Definitely +1 for showing this. I'll let you know after I've done my testing. – icecub Dec 01 '18 at 02:00
  • It can be absolutely positioned aswell, but entire container. – bigless Dec 01 '18 at 02:01
  • I'll have to mess around with it for a while cause the positioning is messing up my design. But it's definitely working so I'll accept your answer as the other answer still isn't undeleted. – icecub Dec 01 '18 at 02:19
  • Ye, the `transform:translateY(100%);` on `.chatroom` is causing the entire container to move underneath its main container. There's basicly this code: `
    `. So that translate causes the room to move underneath the `chatrooms` container. Any on how to solve that?
    – icecub Dec 01 '18 at 02:31
  • @icecub Yes, `overflow: hidden` on chatrooms container. The wrapper container that does not scroll ofc. – bigless Dec 01 '18 at 02:33
  • That didn't work. Just makes me unable to display it again by unchecking the position in browser tools – icecub Dec 01 '18 at 02:36
  • It's not making sense though. It does show me the chatters container isn't larger than the screen. Looks like the `chatroom` is taken out of the document flow and placed underneath it. Not contained.. – icecub Dec 01 '18 at 02:38
  • @icecub Multiple chatrooms make it little bit complicated. I'll try to edit it that way.. – bigless Dec 01 '18 at 02:45
  • That'd be amazing! I'll keep working on it here as well – icecub Dec 01 '18 at 02:51
  • Well I've tried my best. Can't get it done. If I combine your code with a previous answer, I can get it almost completely working. The only downside is that it only animates the last message. All previous messages instantly jump up and I can't get that part fixed. – icecub Dec 01 '18 at 03:40
  • @icecub I'm almost there. This it that kind of question looking easy to answer and then stucked for 2hours) – bigless Dec 01 '18 at 03:49
  • That's amazing! I should mention one more thing though, before I have to come back again.. Top messages can't just disappear into nothing. Some kind of auto overflow needs to be there. Obviously the chat would have to scroll to bottom on each message though. I can do both those things myself, but when I did it with your code, the auto scrolling to bottom messed up your animation. So perhaps you can look at that as well? – icecub Dec 01 '18 at 03:55
  • The code for auto-scrolling to bottom is easy: `elem.scrollTop = elem.scrollHeight;` Where `elem` is the messages container – icecub Dec 01 '18 at 03:56
  • @icecub code updated. autoscrolling will be another challenge as this simple solution breaks animations. – bigless Dec 01 '18 at 04:15
  • Alright. Let me see what I can do with what you've done so far. And really man, thanks a lot for all your help so far! I really appreciate it. – icecub Dec 01 '18 at 04:18
  • @icecub you can try to use jquery scroll animation and sync times wih css or handle all animations via jquery. the thing is that it sets full height before animation and scrollTop anchors that move at bottom. – bigless Dec 01 '18 at 04:30
  • I'll figure it out somehow. You've already done me a huge favor so I'm not gonna ask more of you. Thanks a lot! – icecub Dec 01 '18 at 04:35