Coder Perfect

Only the top row of an HTML table should be frozen (Fixed Table Header Scrolling)


I’d like to construct a table in HTML with the top row frozen (so when you scroll down vertically you can always see it).

Is there a creative method to achieve this without using javascript?

I don’t require the left column to be frozen.

Asked by Davis Dimitriov

Solution #1

I know there are multiple answers to this, but none of them were particularly helpful to me. I came across [this article][1], which explains why my sticky wasn’t working properly.

You can’t use position: sticky; on thead> or tr> components, in general. They can, however, be utilized on th>.

The following is the very minimum of code I required to make it work:

table {
  text-align: left;
  position: relative;

th {
  background: white;
  position: sticky;
  top: 0;

The th> can be set to sticky with the table set to relative and the top at 0 [1]:

NOTE: A div with max-height must be used to wrap the table.

<div id="managerTable" >


#managerTable {
    max-height: 500px;
    overflow: auto;

Answered by Joe

Solution #2

Fixed Header Scrolling is the term for this. There are several ways that have been documented:

You won’t be able to do this without JavaScript, especially if you desire cross-browser compatibility.

Any solution has a variety of drawbacks, especially when it comes to cross-browser/version support.


Even if you don’t want to modify the header, but rather the first row of data, the approach remains the same. I wasn’t sure which one you were talking about.

further contemplation My firm assigned me the responsibility of finding a solution that will work in IE7+, Firefox, and Chrome.

It came down to a fundamental problem after many moons of research, striving, and despair. Because most solutions entail utilizing two separate tables, one for the header that will float and stay in place over the second table that contains the data, you’ll need to create fixed height/width columns to get the fixed header.

//float this one right over second table
    <th>Header 1</th>
    <th>Header 2</th>


Some people use the tbody and thead tags as an alternative, but this is incorrect as well because IE won’t let you put a scrollbar on the tbody, which means you can’t limit its height (so stupid IMO).

  <thead style="do some stuff to fix its position">
    <th>Header 1</th>
    <th>Header 2</th>
  <tbody style="No scrolling allowed here!">
     Data here

This method has a number of drawbacks, including ensuring EXACT pixel widths because tables are so cute in that different browsers assign pixels differently based on computations, and you simply CANNOT (AFAIK) guarantee that the distribution will be exact in all circumstances. If your table has borders, it becomes immediately noticeable.

Since you can’t make this assurance, I chose a different strategy and said screw tables. To simulate tables, I utilized divs. This also has issues with positioning the rows and columns (primarily because floating has issues, and utilizing in-line block won’t function in IE7, so I had no choice but to use absolute positioning to put them where they belonged).

Someone created the Slick Grid, which takes a very similar approach to mine, and you can use that as a decent (although difficult) example of how to accomplish this.

Answered by Matthew Cox

Solution #3

I built a DEMO to simply fix the header by setting overflow:auto to the tbody, as described in Pure CSS Scrollable Table with Fixed Header.

table thead tr{

table th,table td{
    width:100px;//fixed width

table  tbody{
  overflow:auto;//set tbody to auto

Answered by JaskeyLam

Solution #4

My main concern was that the cells should not have a fixed width. Which, in any event, did not appear to be operating. I came upon this option, which appears to be exactly what I’m looking for. I’m publishing it here in case it helps anyone else who is looking for a solution. Take a look at this violin

Working Snippet:

Answered by Tom

Solution #5

For the first row of the table, you can use CSS position: sticky; MDN ref:

.table-class tr:first-child>td{
    position: sticky;
    top: 0;

Answered by Chinthaka Fernando

Post is based on