Flexible HTML Table with Fixed Header and Footer around a Scrollable Body

@PaulOB Glad to hear one of those functions were redundant! I’m looking into that table more closely now & was unsure about a few details.

Unfortunately for my use case, I won’t know how much screen estate is available to display the table (it’s handled automatically by a flex container that grows to “absorb” all space available to it) so I can’t possibly assign a fixed height to it. Which brings me to a couple of questions about this:

  1. Can the fixed thead & tfoot automatically assume their positions at the top & bottom, respectively, of their container? i.e., the div container within which the table is placed.

  2. The stretchy rows are kinda unexpected. I get why they do that but, for the purposes of displaying this table, I think each row should only be as tall as they need to be, as in the rest of your demos. If there isn’t enough rows to warrant a scrollbar, then the table should either:

  • Show the table background in the empty space under the rows. The thead & tfoot should remain fixed at the top & bottom of their container despite the lack of rows.

  • Show the table background in the empty space under tfoot. In essence, the tfoot “shifts” upwards to stick under the bottom of the last row.

In both cases, the scrollbar should be hidden away from sight as it has no purpose. Personally, I’d prefer the first option because it doesn’t make much sense, from a user experience perspective, to have tfoot just a couple of rows away from thead. Having it at the bottom of the container/page might not be of much help either but, at least, it maintains consistency whether the table is fully populated or not. Familiarly adds great value to any UI. Speaking of which, on a completely unrelated note, I find SitePoint UI/UX to be incredibly intuitive with the user’s needs at the forefront above all else. I started looking into both StackOverflow & SitePoint at the same time and it’s ridiculous how well SitePoint handles certain features/implementations compared to the alternative.

You probably understand what I mean but, just in case I haven’t made myself clear enough, here’s an image of my suggestion: on the left is the current implementation while the one on the right is my suggestion of a scrollbar with margins the same size as thead & tfoot. The idea being that both are positioned outside the table but the one on the right looks more closely integrated than it really is.

I think you’re likely to be absolutely correct in that it would require some zany JS-magic to pull off. Although, for the sake of comparison, if we were to clone the entire table twice, perhaps it’s not as process-intensive as it might seem at first to run a JS script which adjusts for resizing dynamically. But that’s just me thinking aloud.

Coincidentally, I came across a jQuery plugin on GitHub which attempts to address this very issue and does commendable job of it as seen in this live demo. It even offers an optional parameter to only display a certain number of rows. However, it is of course not without its own issues (limited to one table per page is a significant one) and I think it might be verging dangerously close to the land of JS voo-doo so I wonder what’s everyone here take on it.

You didn’t look at my last post which has an example of scrollbars on just the body. It does need 2 cloned tables to achieve though as there is no other way to do this smoothly.

I will look at your other requirements tomorrow but it’s a bit like trying to hit a moving target :slight_smile:

Fair point, sorry I came across that way! I looked through your last table as well but wasn’t certain whether that was the final version since you mentioned it you didn’t have time to test it out yet. For all intents & purposes, it is the closest I’ve seen to a perfect solution for all my requests. It’s almost unnerving the way the table adapts across different browsers & their various scrollbars.

The only notable drawback—aside from cloning the table twice—I’ve noticed the scrollbar continues to remain visible in a disabled state when there are not enough rows for the table to scroll. This request has existed since the original post because a disabled scrollbar doesn’t have much purpose & detracts visually from an otherwise normal table. To be honest, I’m on the verge of considering to use one of these jQuery scrollbars purely because of the functional value you’ve added to the table already, despite the visible scrollbar.

My last post was concerning your previous table (using 1 clone) and about going down a somewhat different route for it. I love the simplicity of its execution was wondering if it could be worth modifying one of my original requests for the sake of easier code readability & easier maintenance in the long-run. I thought having the scrollbar outside the table (contrary to my request) would make it substantially easier to code so I was willing to run with it along with a few more tweaks that would make it seem like the scrollbar was within the table itself. In addition, I threw in a link to another demo which does a nifty job of tackling this but with its own drawbacks, perhaps it could more useful to you for comparison.

I really do appreciate the time you and others have put into this thread. I’ve tried to keep my requests broadly the same from the original post with other tweaks/suggestions to make things simpler when possible. If something isn’t feasible, please let me know & I’ll try to adjust accordingly. Thank you :smiley:

As I mentioned at the start all these other methods remove the thead and tfoot content from the table and then continually monitor the resize and scroll events to resize them to match the content and even with throttling this produces an effect that in not entirely smooth unlike my demos.

You can see this when you resize and the headers and footers get left behind.

All these js plugins suffer from the same problems but of course without cloning the whole table as in my example it becomes impossible to do othewise. It’s a trade-off that has to be made.

I believe I mentioned in one of the other threads also that it would be wise to check the height of the table before adding the fixed headers. It shouldn’t be too hard to test if the table has more then n number of rows and if so just exit and leave the table alone.

This is a question that leads to many more questions and a container has no height unless you have set it somewhere so it seems you are moving the requirement of height on the table to a height on the container that holds the table. If you are talking about flex containers then their height is based on their content and that means elements would not scroll unless you added a height somewhere. So in effect you are just moving height around from one place to another.

If you are trying to match a height of a column with another column then yes flex will do this but it will not contain the content so that a scrollbar would appear unless you limited its height once again which brings us back to setting a height on the table to start with.

You would need to show me the complete construct of where you want this table placed so that all the dynamics can be taken into account. In the end though an element cannot scroll unless its height is limited in some way and that can only be done by setting a height or in the case of absolutely placed elements supplying both a top and a bottom.

I will look at detecting the height of the table before applying the fixed header and footers which will solve the stretch rows issue and the scrollbar appearance. However, the fact remains that for the body to have the scrollbar only can only be done as in my last example with 2 clones which does exactly what was asked of it.:slight_smile:

I’ve added a check to make sure the table is at least 300px tall before the fixed headers appear.

I’ve applied this fix to the single clone version only.

The scrollbar was set to auto so will disappear also when not needed.

1 Like

Very good point, I should have added a link to it much earlier:


EDIT: How do I embed/preview the CodePen directly in my post?

Pasting the URL should do it.

1 Like

Thanks! Although, it’s a bit weird that the dedicated URL for embedding CodePen (in HTML or iFrame) didn’t do the trick, meaning I can’t adjust the size of the preview… Oh well, it’ll do!

As I suspected you’ve merely moved the height restriction higher up the dom so you can still get the table to scroll and stretch using the 100% of available space instead of a fixed 300px.


There are some things that are not possible in this scenario as you need to keep the scrollbar visible or the tables won’t match up when there’s not enough rows.

Better results could probably be obtained with the 2 clone version but I think the same problem may occur where the header and footer won’t match the table if the scrollbar is set to auto rather than always visible.

You have to remember that CSS is basically static not dynamic and if you want different things to happen when certain requirements are met then you have to use JS to provide that functionality. The problem with using JS in a scenario like this is that you have to continually monitor the table in order to make changes to the other elements when required.

In the end everything is a trade-off. :slight_smile: You either sacrifice performance for a better design or you go with a simpler design and better performance.

1 Like

Very many thanks, I’ll have to commit some time to implementing this solution in my flex structure to see it all in action in situ (and finally stop bumping this thread!). Just right off the bat, would it be possible to ensure the table rows don’t stretch beyond their regular height when there’s not enough rows to fill the table space, as you did before?

The display of the disabled scrollbar is a bit of a thorn among the roses but I can try looking into dynamic JS solutions to address this somehow. Thanks for all your time & help :thumbsup:

I’ve updated the example to not stretch the rows (although I preferred the stretchy rows).

As I said that would require js listening to the resize event. I’ve put together an example here:

These are all proof of concepts and you would need to test carefully and generally for modern browsers only. At present the JS is relying on ids so if you wanted this approach for multiple tables the js would need to be refactored to take that into account (possible a job for the JS forum as my js is basic at best).

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.