I've been trying to figure out a way to take a standard table and create a fixed-column table where the first column is fixed while the rest scrolls. There's a couple ways that I think make sense, so I'll start with that.
The first way that makes sense to me is to simply break the table code format by creating a separate table as the column that we want to be by itself, something like this:
<div class="table-container">
<div class="table-column">
<table>
<thead><tr><th> </th></tr></thead>
<tbody>
<tr><td>Side Header 1</td></tr>
<tr><td>Side Header 2</td></tr>
<tr><td>Side Header 3</td></tr>
<tr><td>Side Header 4</td></tr>
<tr><td>Side Header 5</td></tr>
<tr><td>Side Header 6</td></tr>
</tbody>
</table>
</div>
<div class="table-column" style="overflow-x: auto;">
<table>
<thead>
<tr><th>Top Header 1</th><th>Top Header 2</th></tr>
</thead>
<tbody>
<tr><td>Row 1, Cell 1</td><td>Row 1, Cell 2</td></tr>
<tr><td>Row 2, Cell 1</td><td>Row 2, Cell 2</td></tr>
<tr><td>Row 3, Cell 1</td><td>Row 3, Cell 2</td></tr>
<tr><td>Row 4, Cell 1</td><td>Row 4, Cell 2</td></tr>
<tr><td>Row 5, Cell 1</td><td>Row 5, Cell 2</td></tr>
<tr><td>Row 6, Cell 1</td><td>Row 6, Cell 2</td></tr>
</tbody>
</table>
</div>
</div>
We make the first column have a <th> of just blank space so that the styling for the whole table still fits.
What I really want to do though is make this more of a dynamic process... Obviously in that case (especially using the word 'dynamic') I could just use some JS, but there must be a way to do this in CSS... but there doesn't seem to be anything solid online... so I thought I'd give it a go.
The closest I've been able to come is through using data-attribute:; and td::before, like this:
<div class="box-table">
<table class="text-center hover stripes">
<thead>
<tr>
<th data-label="Cat 1">Cat 1</th>
<th>Cat 2</th>
<th>Cat 3</th>
<th>Cat 4</th>
<th>Cat 5</th>
<th>Cat 6</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Col 1">Col 1</td>
<td>Col 2</td>
<td>Col 3</td>
<td>Col 4</td>
<td>Col 5</td>
<td>Col 6</td>
</tr>
<tr>
<td data-label="Col 1">Col 1</td>
<td>Col 2</td>
<td>Col 3</td>
<td>Col 4</td>
<td>Col 5</td>
<td>Col 6</td>
</tr>
</tbody>
</table>
</div>
<style>
tr > th:first-child,
tr > td:first-child {
padding: 0;
}
tr > th:first-child::before,
tr > td:first-child::before {
content: attr(data-label);
display: inline-block;
position: fixed;
background: #fff;
border-right: 1px solid rgba(0,0,0,0.2);
letter-spacing: 1px;
padding: 0 0.75rem;
}
<style>
Here's a fiddle with what I've gotten so far: https://jsfiddle.net/wn5nonu3/
There's 2 issues I've run into:
td::before (it seems to be showing 'inline' behavior regardless of what I change the display:; value to?).Potential solution to the second problem is to remove the padding causing the row's to be larger, set the first column to a fixed width and add that width to td::before. I still can't fix the first problem though.
I thought I'd share in case anyone has any ideas about how this could possibly work, or whether or not the route I'm taking is even really doable?
jsFiddle: https://jsfiddle.net/wn5nonu3/ (same as one posted above, just for easy finding)
For the record: I know there's a number of great JS options, I just like to limit the amount of scripts I throw on my pages, and this just seems like something that would be useful.
One way you could make it is by using two tables with the same style, but it's a little hard to maintain. You have to make sure both tables are on the same line and that there's no space between them. When you just wrap the table with the actual content in a div that scrolls. Honestly, I wouldn't go there unless you really don't want to use JS, but it's your call.
.table-wrapper {
width: 100%;
white-space: nowrap;
}
.table-firstcolon {
display: inline-block;
vertical-align: top;
}
.table-firstcolon td,
.table-firstcolon th {
width: 60px;
}
.table-content-wrapper {
display: inline-block;
overflow-x: scroll;
vertical-align: top;
max-width: calc(100% - 60px);
}
.table-content-wrapper>table {
display: inline-block;
vertical-align: top;
}
/* Page Setup */
*,
*::after,
*::before {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
height: 100%;
line-height: 1.5;
width: 50%;
}
body {
min-height: 100%;
padding: 5px 10px;
/* this style is only for the fiddle, would be '0' */
width: 100%;
}
/* General Table Styling */
table {
background: #fdfdfd;
border-collapse: collapse;
border-spacing: 0;
}
th {
font-weight: bold;
}
thead,
tbody,
tfoot {
border: 1px solid #f1f1f1;
}
th, td {
padding: 6px;
text-align: left;
}
thead tr:first-child {
font-weight: bold;
border-bottom: 2px solid #eee;
}
tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.025);
}
tr:hover td {
background-color: rgba(0, 0, 0, 0.04);
color: #000;
}
<div class="table-wrapper">
<table class="table-firstcolon text-center hover stripes">
<thead>
<tr>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<th>Row 1</th>
</tr>
<tr>
<th>Row 2</th>
</tr>
<tr>
<th>Row 3</th>
</tr>
<tr>
<th>Row 4</th>
</tr>
<tr>
<th>Row 5</th>
</tr>
<tr>
<th>Row 6</th>
</tr>
</tbody>
</table><!--
--><div class="table-content-wrapper">
<table>
<thead>
<tr>
<th>Column A</th>
<th>Column B</th>
<th>Column C</th>
<th>Column D</th>
<th>Column E</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
<td>D1</td>
<td>E1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
<td>D2</td>
<td>E2</td>
</tr>
<tr>
<td>A3</td>
<td>B3</td>
<td>C3</td>
<td>D3</td>
<td>E3</td>
</tr>
<tr>
<td>A4</td>
<td>B4</td>
<td>C4</td>
<td>D4</td>
<td>E4</td>
</tr>
<tr>
<td>A5</td>
<td>B5</td>
<td>C5</td>
<td>D5</td>
<td>E5</td>
</tr>
<tr>
<td>A6</td>
<td>B6</td>
<td>C6</td>
<td>D6</td>
<td>E6</td>
</tr>
</tbody>
</table>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With