My aim is to create a 3 by 3 grid made of squares, which adjust to the size of the content, have corner numbers, and whose text content is centred both vertically and horizontally. After hours upon hours of attempting different ways to solve this issue, I’m left with a compromise between square cells and overflowing outside the container. I’ve tried different ways to achieve the 1:1 aspect ratio, but the methods haven’t been compatible with my html + css. Height and width are deliberately not set to any specific values to enable the dynamic size of the cells and grid.
The first snippet shows a grid with squares, with a corner number. The only problem is that the content overflows. The grid container has to have position relative because of a label that goes next to the grid positioned with ‘absolute’, and which I could not include here.
The second snippet has the only difference that the ‘aspect-ratio: 1’ has been removed. The cells of the grid do not overflow the grid anymore, but they are not square either.
Is there a way to have square grid cells which adjust to content width and height without overflowing?
.basic-text {
font-size: larger;
font-family: Arial, Helvetica, sans-serif;
}
.fancy-card {
border: 3px solid grey;
border-radius: 15px;
margin: 1em;
}
#output-card {
display: inline-block;
vertical-align: top;
}
#output-grid-container {
margin: 1em;
padding: 2em;
position: relative;
background-color: white;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 20px;
}
.grid-square {
position: relative;
border: 2px solid grey;
border-radius: 3px;
padding: 1em;
aspect-ratio: 1;
display: flex;
justify-content: center;
/* Center horizontally */
align-items: center;
/* Center vertically */
text-align: center;
line-height: 150%;
}
p {
white-space: pre;
text-wrap: wrap;
}
.corner-rating-number {
position: absolute;
bottom: 0.1em;
left: 0.3em;
margin: 0;
padding: 0;
}
select {
height: 2em;
width: 10em;
border-radius: 0.5em;
}
<div class="fancy-card" id="output-card">
<div id="output-grid-container">
<div class="grid-square">
<span class="corner-rating-number basic-text">7</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">8</span>
<p class="basic-text">Pink</p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">9</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">4</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">5</span>
<p class="basic-text">Violet</p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">6</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">1</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">2</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">3</span>
<p class="basic-text">Blue<br><br>Green</p>
</div>
</div>
</div>
.basic-text {
font-size: larger;
font-family: Arial, Helvetica, sans-serif;
}
.fancy-card {
border: 3px solid grey;
border-radius: 15px;
margin: 1em;
}
#output-card {
display: inline-block;
vertical-align: top;
}
#output-grid-container {
margin: 1em;
padding: 2em;
position: relative;
background-color: white;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 20px;
}
.grid-square {
position: relative;
border: 2px solid grey;
border-radius: 3px;
padding: 1em;
display: flex;
justify-content: center;
/* Center horizontally */
align-items: center;
/* Center vertically */
text-align: center;
line-height: 150%;
}
p {
white-space: pre;
text-wrap: wrap;
}
.corner-rating-number {
position: absolute;
bottom: 0.1em;
left: 0.3em;
margin: 0;
padding: 0;
}
select {
height: 2em;
width: 10em;
border-radius: 0.5em;
}
<div class="fancy-card" id="output-card">
<div id="output-grid-container">
<div class="grid-square">
<span class="corner-rating-number basic-text">7</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">8</span>
<p class="basic-text">Pink</p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">9</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">4</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">5</span>
<p class="basic-text">Violet</p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">6</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">1</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">2</span>
<p class="basic-text"></p>
</div>
<div class="grid-square">
<span class="corner-rating-number basic-text">3</span>
<p class="basic-text">Blue<br><br>Green</p>
</div>
</div>
</div>
2
Answers
I solved this by keeping
aspect-ratio: 1
on the squares, and checking what size the squares become. Then I set the column width explicitly to match the current size. This explicitly set size of the squares makes the outer div adjust to the inner size. Relevant code is in the snippet below.If the page is supposed to update reactively, do this: when data for the grid is updated, set flag
squareDimensionsNeedUpdate
truthy. Before DOM update, if flag is truthy,grid-template-columns
has to be set back torepeat(3, 1fr)
in order for the squares to adjust to new contents. After the update, if flag is truthy, set flag falsy, and get and set the grid column width.You ask "Is there a way to have square grid cells that adjust to the width and height of the content without overflowing?", but
aspect-ratio
is about the width-to-height ratio… So under normal conditions you you will not be able to get a square when the height is greater than the width.So all that can be done that
.grid-square
does not stretch and are squares…The easiest way, is to addoverflow: hidden;
ormin-width: 0; minimum height: 0;
: