I'm trying to figure out how to build this base template for a table like structure(I know it's not an actual table), before i put real data to it and refactor it into a React component. I have the auto horizontal scrolling of this table somewhat working, except after a certain amount of horizontal scrolling to the right, the first column disappears off to the left with the sticky cells. I also can't get any auto vertical scrolling to work with the sticky header, and if i try adding a height to the main container, the whole table scrolls vertically, including the header row, instead of the header row staying sticky. I have an example here on https://codesandbox.io/p/devbox/determined-pine-forked-cqwm6f
I've tried doing this with a table also but had similar results with scrolling both horizontally and vertically with a sticky first column and a sticky header. I've tried wrapping the .tr-matrix
class for the row sections with overflow-y: auto;
but then I get two horizontal scroll bars on top of each other. I've tried various other things but I can only seem to either get vertical scrolling working correctly or horizontal scrolling somewhat working correctly, but not both at the same time where the header and first column stay sticky or fixed really. Anyone have any ideas on how to do this properly?
<div className="tr-matrix-container">
<section className="tr-matrix-header">
<span className="tr-header-col tr-zoom-level-cell">hi</span>
<span className="tr-header-col">1</span>
<span className="tr-header-col">2</span>
<span className="tr-header-col">3</span>
<span className="tr-header-col">4</span>
<span className="tr-header-col">5</span>
<span className="tr-header-col">6</span>
</section>
<div className="tr-matrix">
<section className="tr-row">
<span className="tr-resource-cell">Resource Name</span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
</section>
<section className="tr-row">
<span className="tr-resource-cell">Resource Name</span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
</section>
<section className="tr-row">
<span className="tr-resource-cell">Resource Name</span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
</section>
<section className="tr-row">
<span className="tr-resource-cell">Resource Name</span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
</section>
<section className="tr-row">
<span className="tr-resource-cell">Resource Name</span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
<span className="tr-cell"></span>
</section>
</div>
</div>
$headerHeight: 2.5rem;
$resourceCellWidth: 8.5rem;
$rowHeight: 7.5rem;
$rowWidth: 16.625rem;
html,
body {
overflow: hidden;
margin: 0;
padding: 0;
}
.tr-matrix-container {
position: relative;
overflow-x: auto;
// matrix header
.tr-matrix-header {
display: flex;
height: $headerHeight;
.tr-header-col {
position: sticky;
top: 0;
left: 0;
z-index: 1;
width: $rowWidth;
background-color: #333333;
color: #ffffff;
border: 1px solid #cbcbcb;
box-shadow: 0 0.2rem 0.2rem rgba(0, 0, 0, 0.6);
box-sizing: border-box;
flex-shrink: 0;
}
.tr-zoom-level-cell {
position: sticky;
top: 0;
left: 0;
z-index: 2;
width: $resourceCellWidth;
height: $headerHeight;
box-shadow: 0.2rem 0.2rem 0.2rem rgba(0, 0, 0, 0.6);
}
}
// matrix rows
.tr-matrix {
.tr-row {
display: flex;
height: $rowHeight;
}
.tr-resource-cell {
position: sticky;
top: 0;
left: 0;
z-index: 1;
background-color: #ffffff;
width: $resourceCellWidth;
border: 1px solid #cbcbcb;
border-top-width: 0;
box-sizing: border-box;
box-shadow: 0.2rem 0 0.2rem rgba(0, 0, 0, 0.5);
flex-shrink: 0;
}
.tr-cell {
width: $rowWidth;
border: 1px solid #cbcbcb;
border-left-width: 0;
border-top-width: 0;
box-sizing: border-box;
flex-shrink: 0;
}
}
}
Here you go- Fixed/working fork of your code.
To fix the scrollers problem, you need to get rid of the overflows
.
$headerHeight: 2.5rem;
$resourceCellWidth: 8.5rem;
$rowHeight: 7.5rem;
$rowWidth: 16.625rem;
html,
body {
margin: 0;
padding: 0;
box-sizing: border-box;
width: 3000px;
}
.tr-matrix-container {
position: relative;
// matrix header
.tr-matrix-header {
display: flex;
height: $headerHeight;
position: sticky;
top: 0;
left: 0;
.tr-header-col {
z-index: 1;
width: $rowWidth;
background-color: #333333;
color: #ffffff;
border: 1px solid #cbcbcb;
box-shadow: 0 0.2rem 0.2rem rgba(0, 0, 0, 0.6);
box-sizing: border-box;
flex-shrink: 0;
}
.tr-zoom-level-cell {
z-index: 2;
position: sticky;
top: 0;
left: 0;
width: $resourceCellWidth;
height: $headerHeight;
box-shadow: 0.2rem 0.2rem 0.2rem rgba(0, 0, 0, 0.6);
}
}
// matrix rows
.tr-matrix {
.tr-row {
display: flex;
height: $rowHeight;
}
.tr-resource-cell {
position: sticky;
left: 0;
z-index: -1;
background-color: #ffffff;
width: $resourceCellWidth;
border: 1px solid #cbcbcb;
border-top-width: 0;
box-sizing: border-box;
box-shadow: 0.2rem 0 0.2rem rgba(0, 0, 0, 0.5);
flex-shrink: 0;
}
.tr-cell {
width: $rowWidth;
border: 1px solid #cbcbcb;
border-left-width: 0;
border-top-width: 0;
box-sizing: border-box;
flex-shrink: 0;
}
}
}
Except after a certain amount of horizontal scrolling to the right, the first column disappears off to the left with the sticky cells.
This happens when the table is scrolled outside the viewport width. You need to specify the necessary width in the body to fix the issue. Check the code from my fork. (Only the styles.scss
file is changed. Everything else is the same as yours.) Check - MDN ->
It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing block.
I have changed the z-index
of .tr-zoom-level-cell
to prevent the 'hi' from going behind the horizontal and vertical sticky scrollers. Change it according to your liking.