Scrolling bar in a <Table> with "responsive" columns

I'm trying to design a table with a scroll bar. The problem is that the columns don't adjust according to the information contained in the scrollbar. All the columns keep the same proportion because of the scrollbar located in <tbody>. I therefore used Typescript code to modify the width of each column according to its content. It works fine, but the alignment of columns and values is not good. What's more, the scroll bar is inside the last column and alters the style of the buttons contained in the cells. I don't know how to make the columns proportional and aligned according to the values, so that the style of the buttons isn't altered and the scroll bar is more outwards. You can find the code on GitHub in the link "Click here". And on Stackblitz "Click here" Thanks for your help
StackBlitz
Vitejs - Vite (forked) - StackBlitz
Next generation frontend tooling. It's fast!
14 Replies
ἔρως
ἔρως2d ago
have you tried using grid? i've made tables responsive before by using grid
Diolix
DiolixOP2d ago
No I didn't, I will try. But I would like to understand in my case how can I make it works 🙂
ἔρως
ἔρως2d ago
well, instead of using the table to layout it, use grid for the layout
tbody {
width: calc(100% - 2.5em);
display: block; /* <-- right there */
max-height: 8em;
overflow-y: auto;
}
tbody {
width: calc(100% - 2.5em);
display: block; /* <-- right there */
max-height: 8em;
overflow-y: auto;
}
^ this is what makes the table's layout behave like absolute crap
Diolix
DiolixOP21h ago
Thank you for your advice, can you give a little bit more about the code ? maybe you mean replace all of the table code by a grid code ?
ἔρως
ἔρως21h ago
not all of it just the layouting part just for the <tr>
Chris Bolson
Chris Bolson21h ago
There is so much going on in that CSS it is hard to see the wood for the trees. I suspect that one of your issues is that you have applied display:flex to the td cells with the class "action" - this is messing up your column alignment. My first suggestion would be to place the buttons within a container within the cell, something like this:
<td data-column="actions" >
<div class="actions">
<button class="btn-half-sphere edit-btn"></button>
<button class="btn-half-sphere delete-btn"></button>
</div>
</td>
<td data-column="actions" >
<div class="actions">
<button class="btn-half-sphere edit-btn"></button>
<button class="btn-half-sphere delete-btn"></button>
</div>
</td>
ἔρως
ἔρως21h ago
it starts with the tbody having display: block it completely ruins the layouting of the table display: flex for the td just makes it even worse and then adding a div really doesn't help it at all
Diolix
DiolixOP9h ago
@Chris Thanks for your suggestion, it solved part of the problem. @ἔρως Can you to provide more code for your idea, as all the attempts I've made have been unsuccessful.
ἔρως
ἔρως9h ago
literally display: grid with grid-template-columns set on each tr
Diolix
DiolixOP9h ago
@ἔρως Sorry, but this doesn't make the trick, or I haven't code your idea correctly. So please provide any complete fixes to be made. Thank you very much. 🙂
Chris Bolson
Chris Bolson8h ago
As Epic has said, display:block is messing things up. However, in reality there is more to it than that. For example the styling directly on the <th> contents to make them look like buttons is also messing with things (in a similar way to what I mentioned about about the buttons). It would be better to style child elements than the cell itself. I would change the HTML to this:
<table>
<thead>
<tr>
<th data-column="column1" class="cardHeader"><span>Quantity</span></th>
<th data-column="column2" class="cardHeader"><span>Leaflet</span></th>
<th data-column="column3" class="cardHeader"><span>Format</span></th>
<th data-column="actions"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-column="column1">10</td>
<td data-column="column2">A4</td>
<td data-column="column3">Paperback</td>
<td data-column="actions" >
<div class="actions">
<button class="btn-half-sphere edit-btn"></button>
<button class="btn-half-sphere delete-btn"></button>
</div>
</td>
</tr>
...
</tbody>
</table>
<table>
<thead>
<tr>
<th data-column="column1" class="cardHeader"><span>Quantity</span></th>
<th data-column="column2" class="cardHeader"><span>Leaflet</span></th>
<th data-column="column3" class="cardHeader"><span>Format</span></th>
<th data-column="actions"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-column="column1">10</td>
<td data-column="column2">A4</td>
<td data-column="column3">Paperback</td>
<td data-column="actions" >
<div class="actions">
<button class="btn-half-sphere edit-btn"></button>
<button class="btn-half-sphere delete-btn"></button>
</div>
</td>
</tr>
...
</tbody>
</table>
And replace the table related CSS to something like this:
.table-wrapper {
position: relative;
width: 100%;
height: 10em;
overflow-y: auto;
scrollbar-gutter: stable; /* space for scrollbar*/
}
table {
width: 100%;
border-collapse: collapse;
}
thead th{
position: sticky;
top: 0;
background: #f9f9f9;
z-index: 1;
}
th,td {
padding: 8px;
border: none;
text-align: center;
}
/* Styling for table headers (Card-like appearance) */
.cardHeader > span {
padding: 0.5em;
background: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
transition: transform 0.2s, box-shadow 0.2s;
background: linear-gradient(145deg, #ffffff, #f5f5f5);
}
.cardHeader:hover > span {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.table-wrapper {
position: relative;
width: 100%;
height: 10em;
overflow-y: auto;
scrollbar-gutter: stable; /* space for scrollbar*/
}
table {
width: 100%;
border-collapse: collapse;
}
thead th{
position: sticky;
top: 0;
background: #f9f9f9;
z-index: 1;
}
th,td {
padding: 8px;
border: none;
text-align: center;
}
/* Styling for table headers (Card-like appearance) */
.cardHeader > span {
padding: 0.5em;
background: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
transition: transform 0.2s, box-shadow 0.2s;
background: linear-gradient(145deg, #ffffff, #f5f5f5);
}
.cardHeader:hover > span {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
Note - I haven't tried Epics suggestion of using grid, that may be simpler than what I am suggesting.
ἔρως
ἔρως8h ago
the grid idea is just for allowing the tbody to be scrollable while keeping a sensible layout for desktop and mobile, and to make it responsive what ive done in the past is to do something like grid-template-columns: 1f 1f auto 50px and when things get tight i just do 1fr 1fr or 1fr auto or something like that, depending on the expectations and obviously, hide the thead, so it doesnt look scuffed that is one of the things that got me the interview at my current job
Diolix
DiolixOP6h ago
@ἔρως and no need of typescript code ?
ἔρως
ἔρως5h ago
nope, 100% css

Did you find this page helpful?