I have been trying to think of a way to make a table with a fixed first column (and the rest of the table with a horizontal overflow) I saw a post which had a similar question. but the fixed column bit did not seem to be resolved. Help?
-
I'd like to expand this question a little: a friend of mine wants to make a table which wouldn't scale to more than 100% of the page, but would have more than two columns that together should be scrollable in case they need more horizontal space than there is. In effect, this should be similar to Frozen columns in MS Excel. Is that possible? – Rimas Kudelis Sep 04 '10 at 11:09
-
See my answer on similar question: http://stackoverflow.com/a/17557830/1763149 – Marcin Raczyński Jul 09 '13 at 20:49
7 Answers
How about:
table {
table-layout: fixed;
width: 100%;
*margin-left: -100px; /*ie7*/
}
td, th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 10px;
width: 100px;
}
.fix {
position: absolute;
*position: relative; /*ie7*/
margin-left: -100px;
width: 100px;
}
.outer {
position: relative;
}
.inner {
overflow-x: scroll;
overflow-y: visible;
width: 400px;
margin-left: 100px;
}
<div class="outer">
<div class="inner">
<table>
<tr>
<th class=fix></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th class="fix">Col 5</th>
</tr>
<tr>
<th class=fix>Header A</th>
<td>col 1 - A</td>
<td>col 2 - A (WITH LONGER CONTENT)</td>
<td>col 3 - A</td>
<td>col 4 - A</td>
<td class=fix>col 5 - A</td>
</tr>
<tr>
<th class=fix>Header B</th>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td class=fix>col 5 - B</td>
</tr>
<tr>
<th class=fix>Header C</th>
<td>col 1 - C</td>
<td>col 2 - C</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td class=fix>col 5 - C</td>
</tr>
</table>
</div>
</div>
You can test it out in this jsbin: http://jsbin.com/uxecel/4/edit
-
-
This basically works for me but I'd like to start out with the right-most columns of the scrolling div visible. My column titles are dates, with the most-recent date on the far right, and I'd like that to be visible when the
is first displayed. Is there any way to do this programmatically? Is there a way to programmatically move the horizontal scroll bar in either direction? I'd like to have always-available "scroll left" and "scroll right" buttons at the top of the table, since the browser-supported scroll bar is at the bottom and not always immediately visible.
– Kras Aug 01 '13 at 19:21 -
I saw it has a big gap between header column and data columns when I set width of table > all data columns width,does anybody know why and how to fix it? please see here: http://jsbin.com/sesurutojo/edit?output – Justin Aug 23 '15 at 01:42
-
If I use paging via ajax and I have to go to next page then the scroll does not work and all the table properties are lost. How can I get the same table UI but with some ajax request? – Megha kaur Dec 08 '15 at 15:04
-
2This seems to work only if vertical scrolling is not required. For my case there are many rows so scrolling vertically will only scroll the row data but not the row header fixed in this way using position absolute. – Bruce May 23 '16 at 00:00
-
-
@blahdiblah :how to set height for the based on content in fixed column – Yogesh Jun 17 '16 at 18:56
-
-
@bruce I think that vertical scrolling can work if you make the table `position: relative` and then put it in a div that scrolls. That way, the absolute positioning is scrolled along with the rest of the table. – w00t Jan 11 '17 at 15:42
-
@w00t I using rowspan but once i use this code my rowspan doesn't work anymore. Do you know by any chance inner or outer class will affect rowspan – lisa_rao007 Apr 06 '17 at 19:36
Based on skube's approach, I found the minimal set of CSS I needed was:
.horizontal-scroll-except-first-column {
width: 100%;
overflow: auto;
}
.horizontal-scroll-except-first-column > table {
margin-left: 8em;
}
.horizontal-scroll-except-first-column > table > * > tr > th:first-child,
.horizontal-scroll-except-first-column > table > * > tr > td:first-child {
position: absolute;
width: 8em;
margin-left: -8em;
background: #ccc;
}
.horizontal-scroll-except-first-column > table > * > tr > th,
.horizontal-scroll-except-first-column > table > * > tr > td {
/* Without this, if a cell wraps onto two lines, the first column
* will look bad, and may need padding. */
white-space: nowrap;
}
<div class="horizontal-scroll-except-first-column">
<table>
<tbody>
<tr>
<td>FIXED</td> <td>22222</td> <td>33333</td> <td>44444</td> <td>55555</td> <td>66666</td> <td>77777</td> <td>88888</td> <td>99999</td> <td>AAAAA</td> <td>BBBBB</td> <td>CCCCC</td> <td>DDDDD</td> <td>EEEEE</td> <td>FFFFF</td>
</tr>
</tbody>
</table>
</div>

- 29,306
- 13
- 121
- 110
I have a similar table styled like so:
<table style="width:100%; table-layout:fixed">
<tr>
<td style="width: 150px">Hello, World!</td>
<td>
<div>
<pre style="margin:0; overflow:scroll">My preformatted content</pre>
</div>
</td>
</tr>
</table>

- 2,125
- 2
- 10
- 20

- 25,142
- 5
- 62
- 74
-
3
-
[JSFIDDLE demo](https://jsfiddle.net/dx65qwa3/) so that it's more clear what happens here – Erenor Paz Dec 02 '16 at 17:35
-
20
-
4I don't know why this is the accepted answer. The question says: and the rest of the table, which in my point of view includes more than one column... – Jean-Pierre Bécotte Mar 05 '20 at 20:07
-
and the columns should be in sync with the headers, like if the columns scroll; headers should scroll too with the columns. But I don't think they both will be in sync after implementing this solution – Kunal Tyagi Oct 01 '20 at 08:08
You can use below table style to have horizontal scrolling table with fixed first column.
table,
th,
td {
border: 1px solid black;
}
.table-style {
overflow-x: auto;
}
.table-style tr th:first-child {
position: sticky;
left: 0;
z-index: 2;
background-color: white;
}
<div class="table-style">
<table>
<thead>
<tr>
<th>_col1_row1_</th>
<th>_col2_row1_</th>
<th>_col3_row1_</th>
<th>_col4_row1_</th>
<th>_col5_row1_</th>
</tr>
</thead>
<tbody>
<tr>
<th>_col1_row2_</th>
<td>_col2_row2_</td>
<td>_col3_row2_</td>
<td>_col4_row2_</td>
<td>_col5_row2_</td>
</tr>
<tr>
<th>_col1_row3_</th>
<td>_col2_row3_</td>
<td>_col3_row3_</td>
<td>_col4_row3_</td>
<td>_col5_row3_</td>
</tr>
<tr>
<th>_col1_row4_</th>
<td>_col2_row4_</td>
<td>_col3_row4_</td>
<td>_col4_row4_</td>
<td>_col5_row4_</td>
</tr>
<tr>
<th>_col1_row5_</th>
<td>_col2_row5_</td>
<td>_col3_row5_</td>
<td>_col4_row5_</td>
<td>_col5_row5_</td>
</tr>
</tbody>
</table>
Use jQuery DataTables plug-in, it supports fixed header and columns. This example adds fixed column support to the html table "example":
http://datatables.net/extensions/fixedcolumns/
For two fixed columns:
http://www.datatables.net/release-datatables/extensions/FixedColumns/examples/two_columns.html
-
Fixing left hand-side columns is done by using the leftColumns initialisation parameter. This link works http://www.datatables.net/extensions/fixedcolumns/ (today) – jpkeisala May 16 '15 at 08:23
Take a look at this JQuery plugin:
It adds vertical (fixed header row) or horizontal (fixed first column) scrolling to an existing HTML table. There is a demo you can check for both cases of scrolling.

- 2,191
- 2
- 30
- 40

- 7,499
- 18
- 65
- 103
-
6note: this relies on obsoleted features in jquery and has not been updated since about 1 year – Hayk Saakian Mar 03 '13 at 21:19
-
@HaykSaakian Looks like that project is being updated again now? Says this year, and jQuery version 1.7 is required. – Metropolis May 19 '15 at 22:02
Here's an example with fixed first and last columns. Sticky works better than absolute positioning for expanding the rows when the cells have more content.
Note - this also works with rowspan table cells. The table holds its correct shape.
.wrapper {
overflow-x:scroll;
width:100%;
}
table {
table-layout: fixed;
width: 100%;
border-collapse: collapse;
background: white;
}
tr {
border-top: 1px solid #ccc;
}
td, th {
vertical-align: top;
text-align: left;
width:150px;
padding: 5px;
}
.fix {
position:sticky;
background: white;
}
.fix:first-child {
left:0;
width:180px;
}
.fix:last-child {
right:0;
width:120px;
}
<div class="wrapper">
<table>
<thead>
<th class='fix'>Fixed</th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th class='fix'>Fixed</th>
</thead>
<tbody>
<tr>
<td class='fix'>First Content</td>
<td>A1</td>
<td>A2 (with longer content)</td>
<td>A3</td>
<td>A4</td>
<td>A5</td>
<td class='fix'>Last Content</td>
</tr>
<tr>
<td class='fix'>First Content (with longer content)</td>
<td>B1</td>
<td>B2</td>
<td>B3</td>
<td>B4</td>
<td>B5</td>
<td class='fix'>Last Content</td>
</tr>
<tr>
<td class='fix'>First Content</td>
<td>C1</td>
<td>C2</td>
<td>C3</td>
<td>C4</td>
<td>C5</td>
<td class='fix'>Last Content (with longer content)</td>
</tr>
</tbody>
</table>
</div>
Example to play with: https://jsbin.com/qawidijigi/edit?html,css,output

- 17,217
- 6
- 62
- 70