How do I create an HTML table with a fixed/frozen left column and a scrollable body?
I need a simple solution. I know it's similar to some other questions, like:
- HTML table with fixed headers and a fixed column?
- How can I lock the first row and first column of a table when scrolling, possibly using JavaScript and CSS?
But I need just a single left column to be frozen and I would prefer a simple and script-less solution.
Solution 1:
If you want a table where only the columns scroll horizontally, you can position: absolute
the first column (and specify its width explicitly), and then wrap the entire table in an overflow-x: scroll
block. Don't bother trying this in IE7, however...
Relevant HTML & CSS:
table {
border-collapse: separate;
border-spacing: 0;
border-top: 1px solid grey;
}
td, th {
margin: 0;
border: 1px solid grey;
white-space: nowrap;
border-top-width: 0px;
}
div {
width: 500px;
overflow-x: scroll;
margin-left: 5em;
overflow-y: visible;
padding: 0;
}
.headcol {
position: absolute;
width: 5em;
left: 0;
top: auto;
border-top-width: 1px;
/*only relevant for first row*/
margin-top: -1px;
/*compensate for top border*/
}
.headcol:before {
content: 'Row ';
}
.long {
background: yellow;
letter-spacing: 1em;
}
<div>
<table>
<tr><th class="headcol">1</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><th class="headcol">2</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><th class="headcol">3</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><th class="headcol">4</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><th class="headcol">5</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><th class="headcol">6</th><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
</table>
</div>
Fiddle
Solution 2:
You can use sticky
position.
Here is a sample code. This is HTML/CSS solution. No js is required.
.view {
margin: auto;
width: 600px;
}
.wrapper {
position: relative;
overflow: auto;
border: 1px solid black;
white-space: nowrap;
}
.sticky-col {
position: -webkit-sticky;
position: sticky;
background-color: white;
}
.first-col {
width: 100px;
min-width: 100px;
max-width: 100px;
left: 0px;
}
.second-col {
width: 150px;
min-width: 150px;
max-width: 150px;
left: 100px;
}
<div class="view">
<div class="wrapper">
<table class="table">
<thead>
<tr>
<th class="sticky-col first-col">Number</th>
<th class="sticky-col second-col">First Name</th>
<th>Last Name</th>
<th>Employer</th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky-col first-col">1</td>
<td class="sticky-col second-col">Mark</td>
<td>Ham</td>
<td>Micro</td>
</tr>
<tr>
<td class="sticky-col first-col">2</td>
<td class="sticky-col second-col">Jacob</td>
<td>Smith</td>
<td>Adob Adob Adob AdobAdob Adob Adob Adob Adob</td>
</tr>
<tr>
<td class="sticky-col first-col">3</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
</tbody>
</table>
</div>
</div>
codeply code: https://www.codeply.com/p/oZ4NjpvwbO
Solution 3:
For most browsers released after 2017:
You can use the position: sticky
. See https://caniuse.com/#feat=css-sticky.
There is no need for a fixed width column.
Run the code snippet below to see how it works.
.tscroll {
width: 400px;
overflow-x: scroll;
margin-bottom: 10px;
border: solid black 1px;
}
.tscroll table td:first-child {
position: sticky;
left: 0;
background-color: #ddd;
}
.tscroll td, .tscroll th {
border-bottom: dashed #888 1px;
}
<html>
<div class="tscroll">
<table>
<thead>
<tr>
<th></th>
<th colspan="5">Heading 1</th>
<th colspan="8">Heading 2</th>
<th colspan="4">Heading 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>9:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>10:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>11:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>12:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>13:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>14:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>15:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>16:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
<tr>
<td>17:00</td>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
<td>EEE</td>
<td>FFF</td>
<td>GGG</td>
<td>HHH</td>
<td>III</td>
<td>JJJ</td>
<td>KKK</td>
<td>LLL</td>
<td>MMM</td>
<td>NNN</td>
<td>OOO</td>
<td>PPP</td>
<td>QQQ</td>
</tr>
</tbody>
</table>
</div>
Solution 4:
This is an interesting jQuery plugin that creates fixed headers and/or columns. Toggle fixed column to be true on the demo page to see it in action.