0

I am building an interface to display real time records which are provided via Ajax. The records should be shown in a rectangle of a set height, and the newest record should be located at the bottom of this rectangle. As new records come in, they are inserted at the bottom of the rectangle, and the older records move up. When more records than can fit in the rectangle have arrived, the rectangle should have a scroll bar so that old records can be viewed.

Ideally, solely CSS would be used, however, JavaScript/jQuery solutions are acceptable.

My first attempt was to use CSS, and is shown below and also located at https://jsbin.com/juyapihile/edit?html,output. Note that I don't really have two tables, but have only shown two so you can see the records located at the bottom on the first and the lack of the scroll bar on the second.

For this attempt, I included the records in a table which was positioned absolute with bottom equal to 0 within a div which was positioned relative. Unfortunately, when doing so, the scroll bar doesn't work.

How can this be accomplished? Or generically,how can a positioned element have a scroll bar?

<!DOCTYPE html>
<html>
    <head>
        <title>Client Test</title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <style type="text/css">
            .table-container {
                height:100px;
                overflow-y: scroll;
                position: relative;
                border: 1px solid black;
                padding: 5px;
                margin-bottom: 20px;
            }
            #at-bottom {
                position: absolute;
                bottom: 0;
            }
        </style> 
    </head>
    <body>
        <p>This keeps the newest record at the bottom</p>
        <div class="table-container">
            <table id="at-bottom">
                <thead><tr><td>hello</td><td></td></tr></thead>
                <tbody></tbody>
            </table>
        </div>
        <p>This uses a scroll bar</p>
        <div class="table-container">
            <table id="with-scroll">
                <thead><tr><td>hello</td><td></td></tr></thead>
                <tbody></tbody>
            </table>
        </div>
        <p>How do I do both???</p>
        <script type="text/javascript">
            $(function(){
                var count=0;
                setInterval(function(){
                    console.log('x')
                    count++;
                    $("#at-bottom thead tr").clone().appendTo($('#at-bottom tbody')).find('td').eq(1).text(count);
                    $("#with-scroll thead tr").clone().appendTo($('#with-scroll tbody')).find('td').eq(1).text(count);
                    }, 2000);
            });
        </script>
    </body>
</html>

4 Answers 4

1
+50

I read your post again and wasn't sure if you wanted the text at the bottom of the div when the text was shorter than the height of the div. My other answer works if you want the text filling the div from the top and then getting a scrollbar and keeping the last text at the bottom. If you want to keep the text at the bottom all the time, then I would use a flexbox solution as follows:

var wrap = document.getElementById('wrap');
var body = document.getElementById('body');
var count = 0;

setInterval(function() {
  var row = document.createElement("tr");
  var data = document.createElement("td");
  var text = document.createTextNode("Hello " + count);
  count+=1;
  data.appendChild(text);
  row.appendChild(data);
  body.appendChild(row);
  wrap.scrollTop = wrap.scrollHeight - wrap.clientHeight;
}, 1000);
.table-container {
  display:flex;
  flex-direction:column;
  height:75px;
  width:300px;
  border: 1px solid black;
  padding: 5px;
  margin-bottom: 10px;
  justify-content:flex-end;
}
.table-container div {
  overflow-y: auto;
  min-height: 0px;
}
  <div class="table-container">
    <div id="wrap">
      <table>
        <tbody id="body">

        </tbody>
      </table>
    </div>
  </div>

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks fmacdee, Yes, wish the last record to be at the bottom. Something like that shown at jsbin.com/xecapakemu/edit?html,output (sorry, don't know how to make this work using the stackoverflow fiddle, and haven't done true JavaScript for a while, and need to resort to jQuery for a few items). Mostly works, but the last record doesn't remain at the bottom.
In your jsbin example, you needed to put the scrolltop calculation right after the "appendTo" call, it must be inside the interval function so it gets called every time you add a row.
Thanks. Before appending, I added var bottom=wrap.scrollTop === wrap.scrollHeight - wrap.clientHeight;. And then, I only modified scrollTop if bottom is true.
1

The other answer was a good start. You have to remove the "position:absolute". Then, add an id to each div and set the "scrollTop" attribute like this any time you add elements to the table:

var div = document.getElementById('divID');
div.scrollTop = div.scrollHeight - div.clientHeight;

Here it is working:

var div = document.getElementById('divID');
div.scrollTop = div.scrollHeight - div.clientHeight;
.table-container {
  height: 75px;
  overflow-y: auto;
  position: relative;
  border: 1px solid black;
  padding: 5px;
  margin-bottom: 10px;
}
<div class="table-container">
      <table>
          <tbody>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello last</td></tr>
          </tbody>
      </table>
  </div>
  <div id="divID" class="table-container">
      <table>
          <tbody>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello</td></tr>
              <tr><td></td><td>Hello last</td></tr>
          </tbody>
      </table>
  </div>

1 Comment

Didn't mean to upvote this one, but can't change it to zero and certainly shouldn't downvolte.
1

The problem is the inner table's height is as tall as it needs to be, a table can't have a scrollbar, and the outer div's scrollbar is off. Also generally, scrollbars require height to be somewhat specified.

To solve your problem, I think you should remove position absolute on your table. This will cause the div to scroll. Next, every time a new update comes in via ajax you should simply el.scrollTop = 999999999; where el is el = document.querySelector('.table-container')

Also note, you may want to detect when the user is not at the bottom, and not automatically scroll the to the bottom. You can do this, but measuring el.scrollTop and add the height of the div to it and compare the scroll height of the el. This should do it: el.scrollTop + el.height === el.scrollHeight.

2 Comments

Thanks Parris, Based on jsbin.com/juyapihile/edit?html,output, which element is el?
@user1032531 el is table-container, updating!
-1

Remove: position: absolute; on the table:

.table-container {
    height: 200px;
    overflow-y: scroll;
    position: relative;
    border: 1px solid black;
    padding: 5px;
    margin-bottom: 20px;
}
.table-container table {
    bottom: 0;
}
<div class="table-container">
    <table>
        <tbody>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
        </tbody>
    </table>
</div>
<div class="table-container">
    <table>
        <tbody>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
            <tr><td></td><td>Hello</td></tr>
        </tbody>
    </table>
</div>

3 Comments

I wish to locate a table at the bottom of a div. Will not removing position: absolute; on the table prevent this?
True, sorry. Wasn't taking this into account.
No problem. Thanks for the reply.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.