Frozen HTML Table Headers: A Flying Pig, December 1, 2014

Suppose you were a soldier in the American Civil War and received a rather unusual order from a superior officer; make our pigs fly into an enemy fort!

You dare not question the order you've been given. Obeying an order is a matter of life and death, or perhaps beating and imprisonment if you fail to carry out your assigned duties.

You go and ask your subordinates what materials are available for this impossible task. A young private points out that you can cut the wings off of a chicken and glue them on to the pig. He proudly presents to you a concept drawing showing how it works. You point out that the pig has no muscles suitable to make the wings flap, and even if it did, checken wings would provide only a tiny fraction of the loft required for the pig to fly.

Next, another young private offers a bold solution: fire the pig out of a cannon! This is even more absurd! A cannon will have to be made specifically to fit the shape of a pig-shaped projectile. Even worse, the pig cannot possibly survive the journey! Once again, you dare not question the order you have received, so you get to work!

The day of the big battle comes, and by now you've had the pig-cannon manufactured and you're ready to go to battle with it. The pig-cannon is cited as being vital to victory; your superior officer gives you a citation for your outstanding performance and your name goes down in the history books next to Robert Lee and William Sherman.

Sound familiar? It should if you're a web developer!

The modern-day flying pig that I see most frequently in my web development work is the frozen HTML table header. What I mean by this is that clients sometimes ask me to create a web page that contains a table. The table headers must "freeze" to the top of the page so that they are visible as the user scrolls up and down the page.

From a human-centric design point of view, this is an entirely reasonable request. If there are 20 columns on a page with thousands of records, we don't want the user to have to scroll back up to the very top each time he wants to see which data goes underneath which header.

From an HTML-centric design point of view, this is a disaster. HTML simply offers no reasonable way of accomplishing this. The HTML table header is a child of the same table element that contains the data. There is no CSS that is meant to position them separately. In other words, a frozen HTML table header is like a flying pig.

Working for the Army, I was once asked to add this feature to a page that displayed tabular data. It was a rather unpleasant task; everything I tried doing seemed to result is some unexpected behavior. I finally got something that was "good enough", but even that resulted in column headers moving off a few pixels each time the data was resorted; not a good thing.

Are there solutions to the problem already available? Yes! But at the Army, it is frowned upon to use code from unknown sources.

Working with my current client, I received the very same request. I was not about to say no, nor was I feeling inclined to build my own pig-cannon from scratch once again. I wanted to find a pig-cannon that I could use again and again and again. I didn't want to ever again feel frustrated by receiving this request.

I quickly got to work testing a number of different solutions. I immediately tossed out any solution that involved restricting the table display to an element on the page because the requirement was that the table should take up the whole page apart from a few paragraphs at the top.

The remaining solutions mostly fell into two categories.

The first category consists of solutions that use the CSS display:fixed attribute to precisely control the vertical placement of the table header on the page. At first, this seemed like a very good solution, but it caused a problem: fixing the header vertically also fixes it horizontally. With the current version of HTML, I do not believe that there is any way to fix a table header vertically, but not horizontally. As a result, the layout of the page completely breaks when the page is scrolled horizontally.

The second category of solutions is more sophisticated. It uses Javascript to hide the table headers and replace them with absolutely positioned div elements that can be moved about the page as it scrolls so that they are always in the correct place.

I tested two such solutions. The first is Kjellericson's Tablelock. He provides a very good example and the library seemed to work well, at first. However, this solution turned out not to be suitable for what I was doing because when I used it with the jquery DataTables plug-in, the two libraries just didn't play together at all, especially with DataTables' paging functionality. However, if it works in your situation, it's only 258 lines longs and doesn't require any other Javascript libraries to run.

The second solution is jquery.floatThead, a jquery plug-in. That immediately gives you the disadvantage that it doesn't work without jquery, but I found that it plays extremely well with DataTables. It includes functionality to redraw the column widths appropriately when the table content changes. The version that I used is also 820 lines long!

I've selected my pig-cannon of choice!