Reputation: 51
Here is a demo of responsive, perfectly rectangular grids in CSS. No matter the width of the screen, the grid will always form a perfect rectangle.
body {
max-width: 900px;
}
.grid-1 {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
gap: 5px;
max-width: 100%;
width: fit-content;
overflow: hidden;
}
.grid-1>* {
background-color: green;
width: 100px;
height: 100px;
}
.grid-2 {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
gap: 5px;
width: 1000px;
}
.grid-2>* {
background-color: red;
width: 100px;
height: 100px;
}
<div class="grid-1">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="grid-2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
Screenshot:
The problem I encounter happens when I make my columns/rows 1/2 the size and have the grid items occupy 2 rows and 2 columns.
In this second demo, certain window widths will cause the last item in the grid to be a half cell, and that breaks the perfect rectangle.
body {
max-width: 900px;
}
.grid-1 {
display: grid;
grid-template-columns: repeat(auto-fill, 50px);
grid-template-rows: repeat(auto-fill, 50px);
gap: 5px;
max-width: 100%;
width: fit-content;
overflow: hidden;
}
.grid-1>* {
background-color: green;
width: 100px;
height: 100px;
grid-column: span 2;
grid-row: span 2;
}
.grid-2 {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
gap: 10px;
width: 1000px;
}
.grid-2>* {
background-color: red;
width: 100px;
height: 100px;
}
<div class="grid-1">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="grid-2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
With this second approach, half of the time, there will be half-width red grid item as the very last item in the overall grid. Is there a way I can eliminate this and make a responsive, perfect rectangle when using these half-step grids?
Screenshot:
Is there a better approach to solve this issue that uses pure CSS? My grid-ception feels like a slightly janky approach.
EDIT: I need to retain all of the half columns and not restrict the column count to 2N.
Here is a more detailed demo showing why I want the half-grid steps. I would like a tile in the upper right corner that has a visible gap separating it from the other tiles. By using half-grid steps, I can reduce the size of the separation gap without sacrificing additional columns that the green/red tiles would be able to fill.
:root {
--grid-gap: 0.4rem;
--grid-division: 2; /*Integer*/
--tile-base-size: 9.5rem;
--tile-size: calc(
var(--tile-base-size) - (
(var(--grid-division) - 1)
* var(--grid-gap)
)
);
}
.overlay {
grid-column-start: calc(-1 - var(--grid-division));
grid-column-end: -1;
grid-row-start: 1;
grid-row-end: calc(1 + var(--grid-division));
background-color: blue;
}
.filler {
grid-column-start: calc(-2 - var(--grid-division));
grid-column-end: -1;
grid-row-start: 1;
grid-row-end: calc(1 + 2 * var(--grid-division));
}
body {
max-width: 900px;
}
.grid-1 {
display: grid;
grid-template-columns: repeat(auto-fill, calc(var(--tile-size)/var(--grid-division)));
gap: var(--grid-gap);
max-width: 100%;
width: fit-content;
overflow: hidden;
margin: 0 auto;
}
.tile {
background-color: green;
width: var(--tile-base-size);
height: auto;
aspect-ratio: 1;
grid-column: span var(--grid-division);
grid-row: span var(--grid-division);
}
.grid-2 {
display: inline-grid;
grid-template-columns: repeat(auto-fill, calc(var(--tile-base-size)));
column-gap: calc(var(--grid-gap));
justify-content: start;
width: 1000px;
height: var(--tile-base-size);
grid-row: span var(--grid-division);
overflow: hidden;
}
.grid-2 > * {
background-color: red;
width: 100%;
height: auto;
aspect-ratio: 1;
}
<div class="grid-1">
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="grid-2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="filler"></div>
<div class="overlay"></div>
</div>
Upvotes: 0
Views: 91