How to freeze the first row and the first column of an HTML table with CSS, Javascript and JQuery

how to freeze the first row and the first column of an HTML table
Blog Problem Solving Tutorial

This tutorial shows how to block the first row and the first column on scrolling of a table using CSS and JQuery

I was working on an HTML table that displays a list of users and user permission, the first row displays the permission names and the first column displays the name of the users involved. I have noticed that when I strolled toward the right I couldn’t see the user names and scrolling toward the bottom of the table the user permissions disappeared from the top of the table.

So I had the necessity to block the first row of the table and the first column of the table in order to always show the user names and the user permissions.

Freeze the first row or header of a HTML table in CSS.

Freezing the first row of an HTML table is quite simple, to do that we just need to use the tag <thead> and  <tbody> inside our HTML table in order to recognize the header of the table with the body and the values of the same table. In this way, we can easily block the first row of the table. Here is a table sample:


In this case, we just need to block the height of <tbody> in CSS and we also need to modify the style of <tbody> to display the table block with <display: block>. The propriety <overflow: auto> will help to display the scrollbar automatically. Unfortunately using this property we lose the possibility to create a fully responsive table suitable for any device. In order to make the table responsive, we have to be sure to fix the width of any cell and any header cell, otherwise, the table value won’t match with the table header. Here is the CSS for this purpose:

table {
    display: block;
    width: 50em;
    max-width: 100%;
    position: relative;
    overflow-x: auto;
/* block the table height and display the scrollbar */
tbody {
    height: 200px;
    overflow: auto;
    display: block;
/* fix the cell width */ 
th, td {
    width: 3.5em;

Block the first row of an HTML table with JQuery

Now that we know how to freeze a part of the table and how to create a responsive scroll, we need to dynamically block the part of the table that we want to block, in my case the first row and the first column. Unfortunately, CSS can only block rows OR columns, but it can’t block both at the same time. So, please forget the CSS above if you want to block a row and a column of your table at the same time.

What we need to do is trick the CSS and create a JQuery function that simulates the freeze of the row/column during the scrolling. To do this we will use the JS functions scrollTop and scrollLeft, these functions return the number of pixels of the scroll. For more information, please have a look at the official documentation following this link.

First of all, we need to identify the HTML table through an ID, for example <table id="fixed-headers">. Then I need to connect our HTML table with the scroll javascript event in order to run my JS script only during the table scroll. Now I need to create a function that transports the header to the top based on the number of pixels on the axis Y (we just need to move the header up and down). Here is the code:

$('thead').css('transform', 'translateY(' + this.scrollTop + 'px)');

Now I create a function that transports the first column on scroll, this time the column will be transported on the axis X, in other words, we are moving the column left and right. Here is the code:

$('tbody th').css('transform', 'translateX(' + this.scrollLeft + 'px)');

Now I need to assemble the code above with this CSS:

/* style the HTML table */
table {
    display: block;
    width: 50em;
    max-width: 100%;
    position: relative;
/* this will active the scrollbar */
#fixed-headers {
  border-collapse: collapse;
  height: 300px; 
  display: block; 
  overflow: auto; 
/* force the cells to have the same width */
#fixed-headers td {
  padding: 0 4em !important; 
  border: 1px solid #eee  !important;
#fixed-headers thead {
  transform: translateZ(0);
#fixed-headers thead th {
    background: #999;
    text-align: center;
#fixed-headers tbody th {
    text-align: right;
    background: #999;
    transform: translateZ(0);

Here is the final JQuery code:

$(function() {
  $('#fixed-headers').scroll(function(ev) {
     * where the table scroll, change the position of header and first column
    $('thead th').css('transform', 'translateY(' + this.scrollTop + 'px)');
    $('tbody th').css('transform', 'translateX(' + this.scrollLeft + 'px)');

And here is the final result:


To see the whole code in action, please have a look at this task on CodePen at this link:

You May Like

Today we try to analyze the error that appears on the browser inspector and that is a bit tricky to fix and we try to understand what is causing the error, the error is called “Failed to load resource: net::ERR_BLOCKED_BY_CLIENT“. This error is always followed by an URL, this URL is the link that has […]

May 28, 2021

The Fullscreen Any Element Plugin uses the Javascript Fullscreen API in order to make any chosen HTML element on your website in fullscreen. The Fullscreen API adds methods to present a specific Element (and its descendants) in full-screen mode, and to exit full-screen mode once it is no longer needed. This makes it possible to […]

May 24, 2021
styling first letter paragrapher in css

This tutorial aims to style and changing the first letter of an HTML paragraph of the first paragraph (and only the first) of a WordPress post or page. Styling the first letter of a CSS div is very straightforward, CSS provides a selector called “::first-letter” that gets the job done, it finds the first letter […]

May 20, 2021

Click to Leave a Comment