2

It's a recurring question since, like, forever: how to keep the headers fixed on top when scrolling down a table?

Yes, I know that the web isn't designed to show long spreadsheet-like tables, but when a client asks for something like that (because s/he used to those old Excel documents...), you have no choice but comply.

This is to sum up the major problems and attempted solutions with fixing the headers of a table:

  1. a <thead> element can be relatively postioned, but it won't move from its position;
  2. with position: absolute or fixed, the head is "detached" from the rest of the table, and the column widths doesn't match anymore; moreover, you have to reserve some space above the table body;
  3. this can be solved using a different table for just the headers, leaving the body in the other, but won't fix the problem of the different widths of the columns;
  4. you can set the columns with fixed widths, but it's not always applicable depending on your needs - i.e. in case of dynamic or unknown content;
  5. Javascript can adjust the widths of the columns, but accessing to properties like offsetWidth causes a reflow, which is a quite heavy task even for a browser like Chrome or Firefox, and adds an annoying rendering lag with even not-so-large tables but with dynamic content;
  6. you can create a copy of the table, using the first to show the headers and the other to show the body, but this makes the DOM twice as heavy and should rely on Javascript to copy the changes of the content;
  7. using <div>s with display: table-whatever won't actually solve a thing, and deprives you of the chance to add rowspans and colspans.

With the latest technologies of the web, maybe we can try something new. I've experimented a solution using transform: translate which behaves acceptably good (see the fiddle here), and keeps the space above the table body, and the columns width still match.

This of course won't work in IE8 and lower. But it works fine in Chrome, Safari and Firefox. It doesn't work in Opera 12.x and below, but it does work in Opera 15 thanks of its brand new Blink render engine. I've noticed this works better or at least as well with translate than with translate3d: it shows a bit less flickering.

Unfortunately, this doesn't work in IE9 and IE10, and the headers are kept in their positions. It's really a shame since there's no way to detect this behaviour (that I know of).

So, what are your most recent solutions for this problem? I'm looking for CSS and pure Javascript solutions.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
MaxArt
  • 22,200
  • 10
  • 82
  • 81
  • I whipped up a pure CSS solution (posted [here](http://stackoverflow.com/questions/673153/html-table-with-fixed-headers/25818428#25818428)) that fixes all of the problems you identify. It's actually not even all that state-of-the-art (it even works in IE8). The only major limitation compared to normal tables is that you have to set a fixed header height. Check out the fiddles if you're still interested: **[Fluid Width](http://jsfiddle.net/doctorDestructo/kn4xprgx/)** (may need to resize frame to make scrollbar appear); **[Auto Width](http://jsfiddle.net/doctorDestructo/x54uraaq/)** – DoctorDestructo Sep 15 '14 at 05:29

1 Answers1

1

I recently had to do this exact thing for a client and found it be next to impossible. I did find a really good library called SlickGrid, however when it came to translating that to mobile, it just wouldn't work (performance was too big of an issue). If mobile is not a concern of yours then I definitely suggest checking it out. https://github.com/mleibman/SlickGrid

ArrayKnight
  • 6,956
  • 4
  • 17
  • 20