In an application I'm writing, I'm trying to create a 2D grid system that can be expanded indefinitely in any direction. For those of you familiar with LabVIEW, I'm trying to emulate the ability that users have to scroll indefinitely within the front panel and block diagram of VIs.
Using flexbox, I've managed to make it work alright in the upwards, downwards and leftwards directions, but scrolling rightwards is problematic:
The grid works by nesting a resizable "container" div
inside a fixed-size "viewport" div
:
<template>
<div class="expandable-grid-viewport" ...>
<div class="expandable-grid-container" ...>
<div v-for="tile in tiles" ...>
<GridSquare .../>
</div>
</div>
</div>
</template>
These are the hardcoded aspects of these elements' styles:
.expandable-grid-viewport {
display: flex;
min-height: 100%;
min-width: 100%;
overflow: scroll;
}
.expandable-grid-container {
position: relative;
display: flex;
overflow: hidden;
}
I make the grid track an x/y position corresponding to where the user has scrolled, and modify the style of the viewport based on it:
get viewportStyle() {
const [viewportWidth, viewportHeight] = this.viewportDimensions;
return {
"flex-direction": this.yIndex < 0 ? "column" : "column-reverse",
"align-items": this.xIndex < 0 ? "flex-start" : "flex-end",
width: `${viewportWidth}px`,
height: `${viewportHeight}px`
};
}
Essentially, I flip the direction the container expands in as I cross from the positive side of an axis to the negative (or vice versa) so that the viewport is always flush with at least one corner of the container, and the container expands outwards from there:
The issue I'm facing is that flexbox only allows me to reverse rows or columns but not both together. As shown in the code above, I switch between column
and column-reverse
which lets me handle scrolling in the vertical axis properly, but this results in a problem with horizontal scrolling as shown in the GIF. I can change this to be row
and row-reverse
, in which case scrolling in the horizontal direction works fine but not the vertical direction.
Is there a way I can do both together? As well as flexbox I've also tried playing around with CSS grid but I haven't had much success.
That's possible.
Spoiler alert: if you didn't solved all exercices of this GREAT
➡️ Flexbox Froggy - A game for learning CSS
yet, then go learn Flexbox in a very funny and instructive way and then come back (or don't because you'll have found the solution on the way :-) - that's how I remembered it's possible btw).
It's fun, granted!
So here's a Codepen where flex items are displayed on reverse on both directions and below a snippet with spoiler.
.flex {
display: flex;
flex-flow: row-reverse wrap-reverse;
width: 80%;
margin: 5%;
background-color: deeppink;
}
.item {
width: 16%;
margin: 2rem;
padding: 1rem 2rem;
text-align: center;
color: white;
background-color: darkviolet;
}
<h1>flex-flow: row-reverse wrap-reverse;</h1>
<div class="flex">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
</div>