1

I have an HTML table with a large number of rows. I would like one particular row to be visible on the screen at all times, locked at the bottom of the page if the row's actual position is currently scrolled off the bottom of the screen and locked at the top of the page if it's position is actually currently scrolled off the top of the screen. While the row's actual position is visible on the screen then it should scroll normally as part of the table.

How can I achieve this using CSS and JavaScript?

Paul Hunt
  • 3,115
  • 1
  • 20
  • 36
  • Have you tried scrollspy or similar plugins? – mmgross Mar 26 '16 at 09:44
  • What you want is probably a frozen/locked table row. [Here](http://brentmuir.com/projects/freezeheader/demo.html) and [here](http://kjell.haxx.se/tablelock/) are demos of such effects – zgood Mar 26 '16 at 09:51
  • @zgood Yes, that's the kind of effect I'm after but for a row in the middle of the table rather than the header. – Paul Hunt Mar 26 '16 at 09:55

3 Answers3

1

This example is kind of crude but should give you something close to what you are after. You would need to give the <tr> you want to freeze/lock the class "sticky" and attach an event to the document scroll event to monitor when the sticky element comes into view and toggle position fixed.

See this fiddle

JS

$(function() {

  $(document).scroll(function() {
    var $stickyRow = $('tr.sticky'),
        $anchor = $stickyRow.next();

    $stickyRow.removeClass('fixed top bottom');

    if (!isScrolledIntoView($anchor)) {
      var orientation = ($anchor.offset().top < $(window).scrollTop()) ? 'top' : 'bottom';
      $stickyRow.addClass('fixed ' + orientation);
    }
  });

});

function isScrolledIntoView($elem) {
  var $window = $(window);

  var docViewTop = $window.scrollTop();
  var docViewBottom = docViewTop + $window.height();

  var elemTop = $elem.offset().top;
  var elemBottom = elemTop + $elem.height();

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

CSS

tr.fixed {
  position: fixed;
  bottom: 0;
}

tr.fixed.bottom {
  bottom: 0;
}

tr.fixed.top {
  top: 0;
}

The function isScrolledIntoView comes from this StackOverflow answer. Also, note I am checking if the sticky rows closest sibling ($stickyRow.next()) is in view because I am using it as an anchor point.

Community
  • 1
  • 1
zgood
  • 10,696
  • 2
  • 21
  • 26
0

If the table will always be taller than the screen, you do this with just css. In a table such as:

<table>
        <tr>
            <td>one</td>
            <td>two</td>
            <td>three</td>
            <td>four</td>
            <td>five</td>
        </tr>
        <tr style="position: fixed; bottom: 0;">
            <td>sticky one</td>
            <td>sticky two</td>
            <td>sticky three</td>
            <td>sticky four</td>
            <td>sticky five</td>
        </tr>
</table>

The style on the last row will make it stick to the bottom of the page.

EDIT:

To make this only stick to the bottom of the screen if the table is larger than the screen, instead of the inline style (or explicit css), simple javascript can be used to add those styles:

<script>
    var table = document.getElementById('table')
    if (window.innerHeight < table.offsetHeight) {
        var lastrow = document.getElementById('lastrow')
        lastrow.style.position = "fixed"
        lastrow.style.bottom = 0
    }
</script>

This isn't dynamic, but could be easily made so by rechecking the height on some event.

bschlueter
  • 3,069
  • 23
  • 45
  • _"While the row's actual position is visible on the screen then it should scroll normally as part of the table."_ If it is permanently fixed to the bottom of the page then how can it achieve this? – zgood Mar 26 '16 at 10:04
  • You need javascript to calculate the offset of the row as you scroll to determine if it is in view or not, then toggle `position: fixed;` on or off accordingly. – zgood Mar 26 '16 at 10:13
0
.TableId tbody tr:last-child td {
    position: sticky;
    background-color: #67809f;
    bottom: 0;
}
  • 3
    Hi Youssef. Welcome to StackOverflow. Please be sure to add an explanation to all your answers because we are trying to teach the community not just provide source code. Also, this question already has many answers. If your new answer should be preferred to the existing answers then please say why. [How to Answer](https://stackoverflow.com/help/how-to-answer). Kind Regards. – Elletlar Dec 07 '20 at 15:31