It's really difficult to explain what I need in the title, so here's an example.
This is my table:
body {
margin: 0;
padding: 0;
}
header {
margin-bottom: 15px;
display: flex;
justify-content: center;
}
.header__info-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
}
.infoboard__wrapper {
display: flex;
gap: 15px;
background-color: #f1f1f1;
padding: 5px 10px;
border-radius: 10px;
}
.title {
font-size: 30px;
font-weight: bold;
}
.view {
margin: auto;
width: 100vw;
}
table {
border-collapse: collapse;
width: 100%;
table-layout: fixed;
}
th {
position: sticky;
top:0;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
background-color: white;
box-sizing: border-box;
}
table th:not(:nth-child(1)):not(:nth-child(2)) {
width: 300px;
}
tr:nth-child(even) td {
background-color: #dddddd;
}
.wrapper {
position: relative;
/* overflow-x: auto; */
height: 100vh;
}
.sticky-col {
position: sticky;
z-index: 1;
}
th.sticky-col{
z-index: 2;
}
.first-col {
width: 150px;
min-width: 150px;
max-width: 150px;
left: 0;
}
.second-col {
width: 150px;
min-width: 150px;
max-width: 150px;
left: 100px;
}
.wrapped-content{
width: 250px;
white-space: normal;
}
<header>
<div class="header__info-wrapper">
<div class="title">Some Title</div>
<div class="infoboard__wrapper">
<div class="basic__info">
<div>Total Number:</div>
<div>
<ifx-number-indicator id="number__indicator-total"></ifx-number-indicator>
</div>
</div>
<div class="basic__info">
<div>Completed:</div>
<div>
<ifx-number-indicator id="number__indicator-completed"></ifx-number-indicator>
</div>
</div>
<div class="basic__info">
<div>Planned:</div>
<div>
<ifx-number-indicator id="number__indicator-planned"></ifx-number-indicator>
</div>
</div>
</div>
</div>
</header>
<div class="view">
<div class="wrapper">
<table class="table">
<thead>
<tr>
<th class="sticky-col first-col">Preview</th>
<th class="sticky-col second-col">Component</th>
<th>Version 1</th>
<th>Version 2</th>
<th>Version 3</th>
<th>Version 4</th>
<th>Version 5</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><div class="wrapped-content">Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog Goog Goog</div></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>
<tr>
<td class="sticky-col first-col">4</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">5</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">6</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</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>
This is the behavior that I want! Fixed th and fixed first two cols + fixed horizontal scrollbar. The problem is that, because the horizontal scrollbar appears on the body, the whole body is moving! So, the content inside Header moves too. I don't want that. I want the horizontal scrollbar to only move the content inside the table, not the whole body. I want the vertical scollbar to be on the body so the entire page can scroll down.
If you uncomment the overflow-x: auto;, then the horizontal scrollbar moves the table content, but the vertical scrollbar only moves the table content too, and not the entire body, which is what I want! On top of that, because of the header content, there are actually two scrollbars.
How to achieve what I want? How to make the horizontal scrollbar only move the content of the table while the vertical one move the entire page?
Update:
Screenshots of td border before scroll movement.
Screenshots of td border after scroll movement.
Screenshots of th border before scroll movement.
Screenshots of th border after scroll movement.
Borders do not align:
Making the horizontal scrollbar fixed is not possible yet but to make the table X-axis scroll instead of the whole body scrolling Horizontally and set the table height dynamically according to the header. This will result in almost the same impression as your requirements.
The steps needed to be done are:
overflow-x: hidden;
to the body
elementwidth: 100%
and overflow: scroll
to the wrapper
element of the table
.height: calc(100vh - var(--header-height) - 15px);
to the wrapper
element. (15px is the scrollbar height)EDIT: The second problem you are getting is the border getting invisible when you are scrolling horizontally or vertically. I have tried multiple solutions and found the answer. The cause of this problem is the border-collapse: collapse
on the table
element. Revoming it and changing the border-spacing
to 0
does the job and the border now stays while scrolling but there was a problem with this. The td
and th
border overlaps the sibling border and create a thick (2px) border border at some areas. I have solved this issue by removing the border from td
and th
and replacing it with the box-shadow
extending 1px
with 0 blur. Another 1 small change is the table top-border was missing so I have added the border-top: 1px;
to the th
elements in the thead
. Now it looks perfect.
Additionally, I have changed the left
position of .second-col
element "Component" to 150px
. Now this prevents it from moving horizontally as per your comment request.
You can preview the updated result in the snippet below
const headerEl = document.querySelector("header");
const headerHeight = headerEl.offsetHeight;
const wrapperEl = document.querySelector(".wrapper");
wrapperEl.style.setProperty('--header-height', `${headerHeight}px`);
body {
margin: 0;
padding: 0;
overflow-x: hidden;
}
header {
margin-bottom: 15px;
display: flex;
justify-content: center;
}
.header__info-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
}
.infoboard__wrapper {
display: flex;
gap: 15px;
background-color: #f1f1f1;
padding: 5px 10px;
border-radius: 10px;
}
.title {
font-size: 30px;
font-weight: bold;
}
.view {
margin: auto;
width: 100vw;
}
table {
width: 100%;
table-layout: fixed;
/* Removed the border-collapse and added border spacing 0 */
border-spacing: 0;
}
thead tr th {
/* Added the border top to the table header */
border-top: 1px solid #dddddd;
}
th {
position: sticky;
top: 0;
}
td,
th {
text-align: left;
padding: 8px;
/* Removed the border */
border: none;
/* Added the box-shadow as the border */
box-shadow: 0 0 0 1px #dddddd;
background-color: white;
box-sizing: border-box;
}
table th:not(:nth-child(1)):not(:nth-child(2)) {
width: 300px;
}
tr:nth-child(even) td {
background-color: #dddddd;
}
.wrapper {
position: relative;
width: 100%;
height: calc(100vh - var(--header-height) - 15px);
overflow: scroll;
}
.sticky-col {
position: sticky;
z-index: 1;
}
th.sticky-col {
z-index: 2;
}
.first-col {
width: 150px;
min-width: 150px;
max-width: 150px;
left: 0;
}
.second-col {
width: 150px;
min-width: 150px;
max-width: 150px;
left: 150px;
}
.wrapped-content {
width: 250px;
white-space: normal;
}
<header>
<div class="header__info-wrapper">
<div class="title">Some Title</div>
<div class="infoboard__wrapper">
<div class="basic__info">
<div>Total Number:</div>
<div>
<ifx-number-indicator id="number__indicator-total"></ifx-number-indicator>
</div>
</div>
<div class="basic__info">
<div>Completed:</div>
<div>
<ifx-number-indicator id="number__indicator-completed"></ifx-number-indicator>
</div>
</div>
<div class="basic__info">
<div>Planned:</div>
<div>
<ifx-number-indicator id="number__indicator-planned"></ifx-number-indicator>
</div>
</div>
</div>
</div>
</header>
<div class="view">
<div class="wrapper">
<table class="table">
<thead>
<tr>
<th class="sticky-col first-col">Preview</th>
<th class="sticky-col second-col">Component</th>
<th>Version 1</th>
<th>Version 2</th>
<th>Version 3</th>
<th>Version 4</th>
<th>Version 5</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>
<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>
<div class="wrapped-content">Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog Goog Goog
</div>
</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>
<tr>
<td class="sticky-col first-col">4</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">5</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">6</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</td>
<td class="sticky-col second-col">Larry</td>
<td>Wen</td>
<td>Goog Goog Goog GoogGoog Goog Goog Goog Goog Goog</td>
</tr>
<tr>
<td class="sticky-col first-col">7</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>
Note: You might be seeing a little overlap on the last right cells and the td
element right border not aligning properly with the th
element. This is because cells are missing in this table. If you even add empty cells (td
elements) all over the missing spots. It will be fixed and will look perfect. Its summary is: "Make sure that the count td in every tr element matches the count of th
elements that are in the thead
element."