1

So I have a web page with essentially a table view. The body of the table can scroll horizontally and vertically, but the header should always stay on top and only scroll horizontally (to match the position of the body).

My current solution is to keep the header and body in separate divs, with the header having overflow-x: auto and overflow-y: hidden, and the body having overflow: auto.

Then I have JS code to watching on the "scroll" event so I can programmatically update the horizontal scroll position.

It works, but it's ugly and sometimes there's a little lag, where after scrolling the body the header doesn't immediately update the position.

I've looked at answers to similar questions, but I haven't found a better answer to address horizontal scrolling.

I'm not interested in any framework or 3rd party solutions. Thanks!

How can I let a table's body scroll but keep its head fixed in place?

Scott Schafer
  • 487
  • 3
  • 14
  • 1
    Search for position: sticky. – Bulent Nov 02 '20 at 19:10
  • sticky or fixed position are different ways for sure, would be help more if you share some screenshots. – Rinkesh Golwala Nov 02 '20 at 19:59
  • Okay, I think sticky gives me what I want. Take a look and feel free to suggest refinements. https://jsfiddle.net/scotchfaster/s384ftzx/ I had to make the header higher in the z-index so it wouldn't disappear when you scroll down. Otherwise...this seems pretty clean. Thanks! – Scott Schafer Nov 02 '20 at 22:17
  • But, this is not a table! (your fiddle). – iAmOren Nov 02 '20 at 22:53

1 Answers1

2

Pretty simple with:
<th>'s style set to sticky,
top: 0 to stick to top, and
background-color: white to "hide" scrolled rows.

nowrap used for horizontal effect (not necessary).

th {
  position: sticky;
  top: 0;
  background-color: white;
}
<table border="1">
  <tr>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
    <th>sticky blah blah blah sticky </th>
  </tr>
  <tr>
    <td nowrap>normal blah blah blah normal 01</td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
    <td nowrap>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 02</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 03</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 04</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 05</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 06</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 07</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 08</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 09</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 10</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 11</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 12</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 13</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 14</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 15</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 16</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 17</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 18</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 19</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 20</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 21</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 22</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 23</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 24</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 25</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 26</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 27</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 28</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 29</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 30</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 31</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 32</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 33</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 34</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 35</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 36</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 37</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 38</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 39</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
  <tr>
    <td>normal blah blah blah normal 40</td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
    <td>normal blah blah blah normal </td>
  </tr>
</table>
iAmOren
  • 2,760
  • 2
  • 11
  • 23
  • Done. BTW, I said "essentially a table" because it's not really a table but that was the best way to describe it. It's a custom data grid with editing, resizable columns and so on. I completely forgot about the sticky position. Sadly, we have to support IE11 ( I know), and sticky isn't supported there. More research might be required. – Scott Schafer Nov 03 '20 at 19:32
  • 1
    Thank you. Can't you divert your efforts and resources to a more useful goal as to wean the IE users and advance them to Chrome? :) – iAmOren Nov 04 '20 at 00:15
  • 1
    You might want to take a look into: [How to Make Position Sticky Work in IE: Build Your Own CSS Polyfill with JavaScript](https://levelup.gitconnected.com/how-to-make-position-sticky-work-in-ie-build-your-own-css-polyfill-with-javascript-f42f0a3cc9ef). The second result for google seach for [sticky for internet explorer](https://www.google.com/search?q=sticky+for+internet+explorer). – iAmOren Nov 04 '20 at 00:18
  • I've been waging a long battle against IE. When I started at this company five years ago, we had to support IE7. And it's an extremely complex web app. The problem is that our clients are large hospitals, and they are slow to change. Previously I worked in educational software, and it was the same deal with schools. But I've successfully gotten product to agree that certain features won't be supported in IE, so there's that at least. – Scott Schafer Nov 05 '20 at 01:08
  • 1
    @ScottSchafer, for any feature that is not supported by ie/you because of ie, you can (say, menu options, buttons, etc.) add an icon of IE surrounded with a red circle that has a slanted diameter, and an icon of Chrome with a green check-mark sign, with a tooltip that reads "step into the 21st century: dump IE and switch to Chrome! Pass to your supervisor, IT and Board of Directors!" with a `mailto:` pre-populated with subject and detailed explanation why... – iAmOren Nov 05 '20 at 12:12
  • ![No][1] ![IE](https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Internet_Explorer_10%2B11_logo.svg/98px-Internet_Explorer_10%2B11_logo.svg.png) ![No][1] ![OK][2] ![Chrome](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Google_Chrome_icon_%28September_2014%29.svg/96px-Google_Chrome_icon_%28September_2014%29.svg.png) ![OK][2] [1]: https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/X_mark.svg/35px-X_mark.svg.png [2]: https://upload.wikimedia.org/wikipedia/en/thumb/f/fb/Yes_check.svg/35px-Yes_check.svg.png Too bad images are not inlined in comments... – iAmOren Nov 05 '20 at 12:32
  • but what if the scroll on the X axis is within a different element than the body? If it is a nested div down the DOM tree? I had to do a complex thing with event listeners, but I wonder if there is some more simple solution – Arp Nov 21 '22 at 03:15