I have a table that will contain many columns and I would like to add input fields inside header cells, but I would like for the input to fit the width depending on the body content.
This is how it looks like without the input fields:
And this is how it looks like with the input fields:
As it can be seen, columns like 'index' and 'Is Active' are taking too much space, and I would like to maintain the first layout as much as possible. I tried to set input width to 100% and auto, but it doesn't seem to help very much.
The current css looks like:
.table {
font-family: Arial, Helvetica, sans-serif;
}
.table thead {
position: sticky;
top: 0;
}
.table thead th {
border: 1px solid #e4eff8;
background: white;
cursor: pointer;
}
.table thead th.header-label {
cursor: pointer;
background: linear-gradient(0deg, #e4eff8, #4578a2 5%, #e4eff8 150%);
color: white;
border: 1px solid white;
}
.table th,
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
}
.table td {
border: 1px solid #e4eff8;
}
.table input {
width: 100%;
}
<table class="table">
<thead>
<tr>
<th class="header-label">Index</th>
<th class="header-label">Name</th>
<th class="header-label">Phone</th>
<th class="header-label">Company</th>
<th class="header-label">Registered</th>
<th class="header-label">Is Active</th>
</tr>
<tr>
<th><input type="number"></th>
<th><input type="string"></th>
<th><input type="string"></th>
<th><input type="string"></th>
<th><input type="date"></th>
<th><input type="boolean"></th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Paige Bean</td>
<td>+1 (871) 458-2959</td>
<td>MOREGANIC</td>
<td>2018-12-27T11:28:50 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>1</td>
<td>Knox Holman</td>
<td>+1 (880) 497-2808</td>
<td>MAINELAND</td>
<td>2017-05-07T02:54:22 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>2</td>
<td>Brandy Colon</td>
<td>+1 (969) 513-2827</td>
<td>NEXGENE</td>
<td>2017-06-07T06:42:31 -00:00</td>
<td>true</td>
</tr>
<tr>
<td>3</td>
<td>Suzette Austin</td>
<td>+1 (863) 445-3604</td>
<td>JETSILK</td>
<td>2015-10-24T11:10:41 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>4</td>
<td>Downs Cain</td>
<td>+1 (822) 574-2617</td>
<td>INSECTUS</td>
<td>2017-10-19T08:18:09 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>5</td>
<td>Michael Yang</td>
<td>+1 (875) 492-3905</td>
<td>DELPHIDE</td>
<td>2016-08-15T01:31:55 -01:00</td>
<td>false</td>
</tr>
</tbody>
</table>
So how do you make this happen with pure css, without hard coding the width of each column?
Since the text on the input can't be predicted, every input with width:100% tries to get the most width it can. The solution is use a wrapping div with absolute positioning.
This is how it works (it obvious to me that OP understands the "wrapper div with absolute position" trick. The following is intended for someone learning CSS):
.table .tr-inputs th has position: relative so it serves as reference for child absolute positioned objects. We do not set anything about width (so it's completely auto), and we set a padding-bottom: 1.2rem to keep the th with the correct height for our absolute positioned elements (since absolute positioned elements are removed from the flow and "does not take any space").
.table .tr-inputs div is our wrapper div. We set position: absolute and set all top,right,left,bottom to 0. Then, it stretches it self to fill its relative positioned parent, which is our .table .tr-inputs th.
input has width: 100% so it takes all the width of its parent, which is our absolute positioned wrapper div.
.table {
font-family: Arial, Helvetica, sans-serif;
}
.table thead {
position: sticky;
top: 0;
}
.table thead th {
border: 1px solid #e4eff8;
background: white;
cursor: pointer;
}
.table thead th.header-label {
cursor: pointer;
background: linear-gradient(0deg, #e4eff8, #4578a2 5%, #e4eff8 150%);
color: white;
border: 1px solid white;
}
.table th,
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
}
.table td {
border: 1px solid #e4eff8;
}
.table .tr-inputs th {
position: relative;
padding: 0;
padding-bottom: 1.2rem;
margin: 0;
}
.table .tr-inputs div {
position: absolute;
display: inline-block;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.table input {
width: 100%;
box-sizing: border-box;
}
<table class="table">
<thead>
<tr>
<th class="header-label">Index</th>
<th class="header-label">Name</th>
<th class="header-label">Phone</th>
<th class="header-label">Company</th>
<th class="header-label">Registered</th>
<th class="header-label">Is Active</th>
</tr>
<tr class="tr-inputs">
<th>
<div><input type="number"></div>
</th>
<th>
<div><input type="string"></div>
</th>
<th>
<div><input type="string"></div>
</th>
<th>
<div><input type="string"></div>
</th>
<th>
<div><input type="date"></div>
</th>
<th>
<div><input type="boolean"></div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Paige Bean</td>
<td>+1 (871) 458-2959</td>
<td>MOREGANIC</td>
<td>2018-12-27T11:28:50 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>1</td>
<td>Knox Holman</td>
<td>+1 (880) 497-2808</td>
<td>MAINELAND</td>
<td>2017-05-07T02:54:22 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>2</td>
<td>Brandy Colon</td>
<td>+1 (969) 513-2827</td>
<td>NEXGENE</td>
<td>2017-06-07T06:42:31 -00:00</td>
<td>true</td>
</tr>
<tr>
<td>3</td>
<td>Suzette Austin</td>
<td>+1 (863) 445-3604</td>
<td>JETSILK</td>
<td>2015-10-24T11:10:41 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>4</td>
<td>Downs Cain</td>
<td>+1 (822) 574-2617</td>
<td>INSECTUS</td>
<td>2017-10-19T08:18:09 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>5</td>
<td>Michael Yang</td>
<td>+1 (875) 492-3905</td>
<td>DELPHIDE</td>
<td>2016-08-15T01:31:55 -01:00</td>
<td>false</td>
</tr>
</tbody>
</table>
Never position: sticky <thead> elements. Use This solution instead: Table fixed header and scrollable body
Use background-color on <th> elements
Don't use padding on <th> elements - Use it on an inner .header-label <div>
.header-label should be an inner DIV if you want, no need to "classify" <th> elements
type="boolean" is an invalid type value. Use string or rather a type="checkbox"
/*QuickReset*/*{margin:0;box-sizing:border-box;}
/*
tableFixHead
https://stackoverflow.com/a/47923622/383904
*/
.tableFixHead {
overflow-y: auto;
height: 180px;
}
.tableFixHead thead th {
position: sticky;
top: 0;
}
.table {
border-collapse: collapse;
font-family: Arial, Helvetica, sans-serif;
}
.table th {
background: #fff;
}
.table th .header-label {
padding: 0.2rem 0.5rem;
cursor: pointer;
background: linear-gradient(0deg, #e4eff8, #4578a2 5%, #e4eff8 150%);
color: white;
border: 1px solid white;
white-space: nowrap;
}
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
border: 1px solid #e4eff8;
}
.table input {
display: block;
width: 100%;
font: 14px/1.4 sans-serif;
}
<div class="tableFixHead">
<table class="table">
<thead>
<tr>
<th><div class="header-label">Index</div><input type="number"></th>
<th><div class="header-label">Name</div><input type="string"></th>
<th><div class="header-label">Phone</div><input type="string"></th>
<th><div class="header-label">Company</div><input type="string"></th>
<th><div class="header-label">Registered</div><input type="date"></th>
<th><div class="header-label">Is Active</div><input type="string"></th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Paige Bean</td>
<td>+1 (871) 458-2959</td>
<td>MOREGANIC</td>
<td>2018-12-27T11:28:50 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>1</td>
<td>Knox Holman</td>
<td>+1 (880) 497-2808</td>
<td>MAINELAND</td>
<td>2017-05-07T02:54:22 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>2</td>
<td>Brandy Colon</td>
<td>+1 (969) 513-2827</td>
<td>NEXGENE</td>
<td>2017-06-07T06:42:31 -00:00</td>
<td>true</td>
</tr>
<tr>
<td>3</td>
<td>Suzette Austin</td>
<td>+1 (863) 445-3604</td>
<td>JETSILK</td>
<td>2015-10-24T11:10:41 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>4</td>
<td>Downs Cain</td>
<td>+1 (822) 574-2617</td>
<td>INSECTUS</td>
<td>2017-10-19T08:18:09 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>5</td>
<td>Michael Yang</td>
<td>+1 (875) 492-3905</td>
<td>DELPHIDE</td>
<td>2016-08-15T01:31:55 -01:00</td>
<td>false</td>
</tr>
</tbody>
</table>
</div>
As a workaround you could use absolute position inputs and relative position wrapper around it to match the column size.
I dont think it is a good solution but it works.
As mentioned in the answer from #Roko C. Buljan there are some points you could do better.
.table {
font-family: Arial, Helvetica, sans-serif;
}
.table thead {
position: sticky;
top: 0;
}
.table thead th {
border: 1px solid #e4eff8;
background: white;
cursor: pointer;
}
.table thead th.header-label {
cursor: pointer;
background: linear-gradient(0deg, #e4eff8, #4578a2 5%, #e4eff8 150%);
color: white;
border: 1px solid white;
}
.table th,
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
position: realtive;
}
.table td {
border: 1px solid #e4eff8;
}
.table .input_wrapper{
position: relative;
width: 100%;
display: block;
}
.table .input_wrapper::after{
content: "+";
color: rgba(0, 0, 0, 0);
display: block;
}
.table input {
position: absolute;
width: 100%;
left: 0;
}
<table class="table">
<thead>
<tr>
<th class="header-label">Index</th>
<th class="header-label">Name</th>
<th class="header-label">Phone</th>
<th class="header-label">Company</th>
<th class="header-label">Registered</th>
<th class="header-label">Is Active</th>
</tr>
<tr>
<th>
<div class="input_wrapper"><input type="number"></div>
</th>
<th>
<div class="input_wrapper"><input type=" string"></div>
</th>
<th>
<div class="input_wrapper"><input type="string"></div>
</th>
<th>
<div class="input_wrapper"><input type="string"></div>
</th>
<th>
<div class="input_wrapper"><input type="date"></div>
</th>
<th>
<div class="input_wrapper"><input type="boolean"></div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Paige Bean</td>
<td>+1 (871) 458-2959</td>
<td>MOREGANIC</td>
<td>2018-12-27T11:28:50 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>1</td>
<td>Knox Holman</td>
<td>+1 (880) 497-2808</td>
<td>MAINELAND</td>
<td>2017-05-07T02:54:22 -01:00</td>
<td>false</td>
</tr>
<tr>
<td>2</td>
<td>Brandy Colon</td>
<td>+1 (969) 513-2827</td>
<td>NEXGENE</td>
<td>2017-06-07T06:42:31 -00:00</td>
<td>true</td>
</tr>
<tr>
<td>3</td>
<td>Suzette Austin</td>
<td>+1 (863) 445-3604</td>
<td>JETSILK</td>
<td>2015-10-24T11:10:41 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>4</td>
<td>Downs Cain</td>
<td>+1 (822) 574-2617</td>
<td>INSECTUS</td>
<td>2017-10-19T08:18:09 -01:00</td>
<td>true</td>
</tr>
<tr>
<td>5</td>
<td>Michael Yang</td>
<td>+1 (875) 492-3905</td>
<td>DELPHIDE</td>
<td>2016-08-15T01:31:55 -01:00</td>
<td>false</td>
</tr>
</tbody>
</table>
this is a simple javascript solution if you want:
change this section of HTML:
<tr>
<th><div class="input-container"><input type="number"></div></th>
<th><div class="input-container"><input type="string"></div></th>
<th><div class="input-container"><input type="string"></div></th>
<th><div class="input-container"><input type="string"></div></th>
<th><div class="input-container"><input type="date"></div></th>
<th><div class="input-container"><input type="boolean"></div></th>
</tr>
add this to your CSS:
table .input-container {
width: 0;
}
and link this javascript to your HTML:
let cont = document.querySelectorAll('.input-container')
for (let i = 0; i < cont.length; i++) {
cont[i].style.width = cont[i].parentNode.offsetWidth + 'px'
}
try this code
.table th {
padding : 0;
padding-right : 0.2rem;
}
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
}
Instead of :
.table th,
.table td {
padding: 0.2rem 0.5rem;
text-align: center;
}
I am trying to create a table that has a scrollable <tbody> with a fixed <thead>. I have achieved that here https://jsfiddle.net/ghnfzwm6/16/.
However, this is not quite what I would like. I want the scroll bar to start where the <tbody> starts. I have attempted to do so by adding
height: 546px;
max-height: 546px;
overflow-y: scroll; /* only Y axis scroll */
to <tbody> and removing it from #tasks-table-wrapper. I also made <tbody> and <tr> display: block;
Here is the result https://jsfiddle.net/4gLwp697/3/. The problem now is that <thead> does not line up with <tbody>. I can fix that by specifying column widths, but I want them to be auto.
How can I fix this?
consider this code snippet, There is no direct solution to your problem, This is determined by the 'table' feature. The solutions for the current mainstream frameworks are as follows, You need to set the width of 'columns'.
* {
margin: 0;
padding: 0;
}
#content {
overflow: hidden;
height: 100%;
text-align: center;
}
#tasks-table-wrapper {
text-align: left;
display: inline-block;
width: auto;
}
.scrollbar-wrap {
overflow: auto;
height: 100px;
}
.black-table {
border-collapse: separate;
font-size: 0;
background-color: #121212;
text-transform: uppercase;
border-spacing: 0;
}
.black-table td {
color: #bbb;
font-size: 11px;
letter-spacing: 1px;
padding: 15px 30px;
}
.black-table th {
color: #fff;
font-size: 12px;
font-weight: 700;
letter-spacing: 2px;
padding: 15px 25px;
border-bottom: 1px solid #1c1c1c;
position: sticky; /* keep TH on top */
top: 0;
background-color: #121212;
white-space: nowrap;
}
<div id="content">
<div id="tasks-table-wrapper">
<table class="black-table">
<colgroup>
<col width="180">
<col width="180">
<col width="180">
<col width="180">
</colgroup>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
</table>
<div class="scrollbar-wrap">
<table class="black-table">
<colgroup>
<col width="180">
<col width="180">
<col width="180">
<col width="163">
</colgroup>
<tbody>
<tr>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
</tr>
<tr>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
</tr>
<tr>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
</tr>
<tr>
<td>AAA</td>
<td>BBB</td>
<td>CCC</td>
<td>DDD</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
You can see VUE Table with fixed header, Review the table elements.
Replace
#tasks tr {
display: block;
}
with
#tasks tr {
display: table;
width: 100%;
table-layout: fixed;
}
https://jsfiddle.net/5nt18cL0/
I have a table that uses rowspan for one of the table headers. This table also switches to a fixed column style on smaller sizes. The issue I'm running into is on smaller sizes, when the th with the rowspan becomes fixed, it messes up the structure of the remaning th.
A solution I thought of was to just have an empty th above Foods so I didn't have to use a rowspan, but due to ADA requirments, that's not an option.
Here's some code: CODEPEN
This is the large screen view - you can see there's a Foods column as well as two groups, each of which containing two columns.
Here's a view of when it goes to the fixed column layout. You can see that Group 1 - Col 1 now takes the place where Foods used to be, and the entire 2nd shifted.
HTML:
<div class="wrap">
<table>
<thead>
<tr>
<th rowspan="2" class="fixed">Foods</th>
<th colspan="2">Group 1</th>
<th colspan="2">Group 2</th>
</tr>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fixed">Tacos</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
<tr>
<td class="fixed">Pizza</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
</tbody>
</table>
</div>
CSS:
table {
border: solid 1px black;
border-spacing: 0;
border-collapse: collapse;
width: 900px;
}
th {
vertical-align: bottom;
padding: 5px 10px;
border-left: solid 1px grey;
}
th[colspan="2"] {
border-bottom: solid 1px grey;
}
td {
border-top: solid 1px grey;
}
tbody tr:nth-child(odd) td {
background: grey;
}
.fixed {
border-left: none;
}
#media (max-width: 600px) {
.fixed {
position: absolute;
width: 50px;
left: 0;
}
.wrap {
overflow-x: scroll;
overflow-y: visible;
margin-left: 50px;
}
}
I am not really sure about the issue but it seems to be related to the use of position:fixed. You are removing the elements from the flow so it's like they no more belong to the table making the table algorithm behave strange.
An idea of fix is to consider a extra element that you make visible on small screen to avoid this issue. Basically this element will correct the table layout when you make some of the element position:fixed
* {
text-align: center;
font-weight: normal;
}
table {
border: solid 1px black;
border-spacing: 0;
border-collapse: collapse;
width: 900px;
}
th {
vertical-align: bottom;
padding: 5px 10px;
border-left: solid 1px grey;
}
th[colspan="2"] {
border-bottom: solid 1px grey;
}
td {
border-top: solid 1px grey;
}
tbody tr:nth-child(odd) td {
background: grey;
}
.fixed {
border-left: none;
}
.fix {
padding:0;
border:none;
}
#media (min-width:700px) {
.fix {
display:none;
}
}
#media (max-width: 700px) {
.fixed {
position: absolute;
width: 50px;
left: 0;
}
.wrap {
overflow-x: scroll;
overflow-y: visible;
margin-left: 50px;
}
}
<div class="wrap">
<table>
<thead>
<tr>
<th rowspan="2" class="fixed">Foods</th>
<th colspan="2">Group 1</th>
<th colspan="2">Group 2</th>
</tr>
<tr>
<th class="fix"></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fixed">Tacos</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
<tr>
<td class="fixed">Pizza</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
</tbody>
</table>
</div>
To avoid extra element you can consider pseudo element:
* {
text-align: center;
font-weight: normal;
}
table {
border: solid 1px black;
border-spacing: 0;
border-collapse: collapse;
width: 900px;
}
th {
vertical-align: bottom;
padding: 5px 10px;
border-left: solid 1px grey;
}
th[colspan="2"] {
border-bottom: solid 1px grey;
}
td {
border-top: solid 1px grey;
}
tbody tr:nth-child(odd) td {
background: grey;
}
.fixed {
border-left: none;
}
thead > tr:last-child::before {
content:"";
display:table-cell;
padding:0;
border:none;
}
#media (min-width:700px) {
thead > tr:last-child::before {
display:none;
}
}
#media (max-width: 700px) {
.fixed {
position: absolute;
width: 50px;
left: 0;
}
.wrap {
overflow-x: scroll;
overflow-y: visible;
margin-left: 50px;
}
}
<div class="wrap">
<table>
<thead>
<tr>
<th rowspan="2" class="fixed">Foods</th>
<th colspan="2">Group 1</th>
<th colspan="2">Group 2</th>
</tr>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fixed">Tacos</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
<tr>
<td class="fixed">Pizza</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
<td>blank</td>
</tr>
</tbody>
</table>
</div>
How to make the horizontal scroll bar only affects the gray columns in the following illustration.
html,
body {
background: #ccc;
font-family: Arial, sans-serif
}
#table {
background: white;
margin: 100px auto;
width: 400px;
overflow: auto;
text-align: center;
}
#inner-table {
border-collapse: collapse;
border-radius: 3px;
overflow: hidden
}
td,
th {
padding: 5px 10px;
}
th {
border-bottom: 1px solid #B8C2CC
}
.sticky {
background-color: #1C3D5A;
color: #dae1e7;
}
.scroll {
background-color: #B8C2CC;
color: #22292f
}
<div id="table">
<table id="inner-table">
<thead>
<tr>
<th class="sticky">sticky</th>
<th class="sticky">sticky</th>
<th class="scroll">scroll</th>
<th class="scroll">scroll</th>
<th class="scroll">scroll</th>
<th class="scroll">scroll</th>
<th class="scroll">scroll</th>
<th class="scroll">scroll</th>
<th class="sticky">sticky</th>
<th class="sticky">sticky</th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky">1</td>
<td class="sticky">2</td>
<td class="scroll">3</td>
<td class="scroll">4</td>
<td class="scroll">5</td>
<td class="scroll">6</td>
<td class="scroll">7</td>
<td class="scroll">8</td>
<td class="sticky">9</td>
<td class="sticky">10</td>
</tr>
<tr>
<td class="sticky">11</td>
<td class="sticky">12</td>
<td class="scroll">13</td>
<td class="scroll">14</td>
<td class="scroll">15</td>
<td class="scroll">16</td>
<td class="scroll">17</td>
<td class="scroll">18</td>
<td class="sticky">19</td>
<td class="sticky">20</td>
</tr>
</tbody>
</table>
</div>
This was rather more difficult to put together than I anticipated - and even now, I am wondering if there isn't a much simpler approach.
The approach below utilises:
an outer container which contains two position: absolute tables
a fixed-width inner container - using margins for positioning inside the outer container - with a scrollbar, which allows you to see the oversized table it contains
Working Example:
html,
body {
background: #ccc;
font-family: Arial, sans-serif
}
.outer-container {
position: relative;
background-color: white;
margin: 40px auto;
width: 400px;
overflow: hidden;
text-align: center;
}
.outer-container,
.inner-container {
height: 125px;
}
table {
height: 108px;
}
.inner-container table {
border-radius: 3px;
}
td, th {
padding: 5px 10px;
}
th {
border-bottom: 1px solid #B8C2CC
}
.fixed-table th,
.fixed-table td {
background-color: #1C3D5A;
color: #dae1e7;
}
.inner-container {
margin: 0 130px;
max-width: 612px;
overflow: auto;
}
.inner-container > table {
background-color: #B8C2CC;
color: #22292f
}
.outer-container > table {
position: absolute;
top: 0;
border-collapse: collapse;
}
.outer-container > table:nth-of-type(1) {
left: 0;
}
.outer-container > table:nth-of-type(2) {
right: 0;
}
<div class="outer-container">
<table class="fixed-table">
<thead>
<tr>
<th>sticky</th>
<th>sticky</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>11</td>
<td>12</td>
</tr>
</tbody>
</table>
<div class="inner-container">
<table>
<thead>
<tr>
<th>scroll</th>
<th>scroll</th>
<th>scroll</th>
<th>scroll</th>
<th>scroll</th>
<th>scroll</th>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
<td>17</td>
<td>18</td>
</tr>
</tbody>
</table>
</div>
<table class="fixed-table">
<thead>
<tr>
<th>sticky</th>
<th>sticky</th>
</tr>
</thead>
<tbody>
<tr>
<td>9</td>
<td>10</td>
</tr>
<tr>
<td>19</td>
<td>20</td>
</tr>
</tbody>
</table>
</div>
CSS3 should do the job.
table {
position: relative;
padding-left: (width-of-your-td-elements);
}
table td:first-of-type {
position: absolute;
left: 0;
}
Sources
I have a table that can slide left or right when the screen is narrow enough. The first column is positioned absolute so that it is always visible.
Is it possible to make the cells in the first column maintain the size of the cells in the other columns? I am not sure how to achieve this while keeping the first column frozen.
Here is a fiddle to my code: http://jsfiddle.net/ta945/
Here's the HTML and CSS
HTML:
<div>
<table>
<thead>
<tr>
<th class="sticky">Name</th>
<th>Helpful Services</th>
<th>State</th>
<th>City</th>
<th>Phone</th>
<th>URL</th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky">First Name</td>
<td>Math</td>
<td>CO</td>
<td>San Francisco</td>
<td>123-456-7890</td>
<td>http://somewhere.com</td>
</tr>
<tr>
<td class="sticky">Second Name</td>
<td>Reading</td>
<td>NY</td>
<td>New York City</td>
<td>123-456-7890</td>
<td>http://somewhere.com</td>
</tr>
<tr>
<td class="sticky">Third Name</td>
<td>Art</td>
<td>IL</td>
<td>Chicago</td>
<td>123-456-7890</td>
<td>http://somewhere.com</td>
</tr>
<tr>
<td class="sticky">Four Name</td>
<td>Programming</td>
<td>IL</td>
<td>Chicago</td>
<td>123-456-7890</td>
<td>http://somewhere.com</td>
</tr>
</tbody>
</table>
</div>
CSS:
div {
width: 100%;
border: 1px solid #000000;
overflow-y: hidden;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
}
table {
border-collapse: seperate;
border-spacing: 0;
margin-left: 5em;
}
thead, tbody, tr {
vertical-align: middle;
}
th {
font-weight: bold;
padding: 2px 4px;
background-color: #676767;
color: #FFFFFF
}
td {
padding: 2px 4px;
}
tbody tr:nth-child(even) td {
background-color: #cccccc;
}
.sticky {
position: absolute;
left: 0;
top: auto;
margin-left: 9px;
}