How to make a grid container shrink to fit the content?
I'm trying to make a game with a grid. I have x divs with x divs inside them, to create the grid.
The problem is that I want the container div for all of this to only be as big as it needs to be (say, 5x5 squares at 25px each = 125px x 125px container div). The height is fine, but the width stretches to the end. Each box is to be 25px.
I've tried grid-template-rows: repeat(auto-fill, 25px)
which doesn't seem to work. I can't set it to a specific width (125px) because the amount of squares is going to be dynamic (but always a square number).
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
#start {
position: relative;
width: auto;
margin: 50px auto;
display: grid;
grid-template-rows: repeat(auto-fill, 25px);
}
.row {
display: grid;
grid-template-columns: repeat(auto-fill, 25px);
}
.gameNode {
margin: 0px;
height: 25px;
width: 25px;
}
.even {
background-color: #666;
}
.odd {
background-color: #999;
}
<div id="start">
<div id="row_0" class="row">
<div class="gameNode odd" id="node_1"></div>
<div class="gameNode even" id="node_2"></div>
<div class="gameNode odd" id="node_3"></div>
<div class="gameNode even" id="node_4"></div>
<div class="gameNode odd" id="node_5"></div>
</div>
<div id="row_1" class="row">
<div class="gameNode even" id="node_6"></div>
<div class="gameNode odd" id="node_7"></div>
<div class="gameNode even" id="node_8"></div>
<div class="gameNode odd" id="node_9"></div>
<div class="gameNode even" id="node_10"></div>
</div>
<div id="row_2" class="row">
<div class="gameNode odd" id="node_11"></div>
<div class="gameNode even" id="node_12"></div>
<div class="gameNode odd" id="node_13"></div>
<div class="gameNode even" id="node_14"></div>
<div class="gameNode odd" id="node_15"></div>
</div>
<div id="row_3" class="row">
<div class="gameNode even" id="node_16"></div>
<div class="gameNode odd" id="node_17"></div>
<div class="gameNode even" id="node_18"></div>
<div class="gameNode odd" id="node_19"></div>
<div class="gameNode even" id="node_20"></div>
</div>
<div id="row_4" class="row">
<div class="gameNode odd" id="node_21"></div>
<div class="gameNode even" id="node_22"></div>
<div class="gameNode odd" id="node_23"></div>
<div class="gameNode even" id="node_24"></div>
<div class="gameNode odd" id="node_25"></div>
</div>
</div>
I expected the container div to take up only as much space as the squares, but it stretches across the entire page. The height seems fine.
Here is a screenshot of what it's doing:
It's creating a bunch of extra squares, filling the space rather than only filling the actual divs.
Am I handling this correctly, or should I be formatting my HTML differently to get the desired effect?
Answer #1:
Grid won't work in this case. You need to use flexbox. Switch to display: inline-flex
on the primary container.
display: grid
You can't use display: grid
because that creates a block level container which, by default, occupies the full width of the parent. Since you can't define a width because:
I can't set it to a specific width because the amount of squares is going to be dynamic...
...then you can't use a block-level container. So that's where you stand now:
#start {
display: grid;
border: 2px solid red;
}
.row {
display: grid;
grid-template-columns: repeat(auto-fill, 25px);
grid-auto-rows: 25px;
}
.even { background-color: #666; }
.odd { background-color: #999; }
<div id="start">
<div id="row_0" class="row">
<div class="gameNode odd" id="node_1"></div>
<div class="gameNode even" id="node_2"></div>
<div class="gameNode odd" id="node_3"></div>
<div class="gameNode even" id="node_4"></div>
<div class="gameNode odd" id="node_5"></div>
</div>
<div id="row_1" class="row">
<div class="gameNode even" id="node_6"></div>
<div class="gameNode odd" id="node_7"></div>
<div class="gameNode even" id="node_8"></div>
<div class="gameNode odd" id="node_9"></div>
<div class="gameNode even" id="node_10"></div>
</div>
<div id="row_2" class="row">
<div class="gameNode odd" id="node_11"></div>
<div class="gameNode even" id="node_12"></div>
<div class="gameNode odd" id="node_13"></div>
<div class="gameNode even" id="node_14"></div>
<div class="gameNode odd" id="node_15"></div>
</div>
<div id="row_3" class="row">
<div class="gameNode even" id="node_16"></div>
<div class="gameNode odd" id="node_17"></div>
<div class="gameNode even" id="node_18"></div>
<div class="gameNode odd" id="node_19"></div>
<div class="gameNode even" id="node_20"></div>
</div>
<div id="row_4" class="row">
<div class="gameNode odd" id="node_21"></div>
<div class="gameNode even" id="node_22"></div>
<div class="gameNode odd" id="node_23"></div>
<div class="gameNode even" id="node_24"></div>
<div class="gameNode odd" id="node_25"></div>
</div>
</div>
display: inline-grid
You can't use display: inline-grid
because all items will stack vertically.
#start {
display: inline-grid;
border: 2px solid red;
}
.row {
display: grid;
grid-template-columns: repeat(auto-fill, 25px);
grid-auto-rows: 25px;
}
.even { background-color: #666; }
.odd { background-color: #999; }
<div id="start">
<div id="row_0" class="row">
<div class="gameNode odd" id="node_1"></div>
<div class="gameNode even" id="node_2"></div>
<div class="gameNode odd" id="node_3"></div>
<div class="gameNode even" id="node_4"></div>
<div class="gameNode odd" id="node_5"></div>
</div>
<div id="row_1" class="row">
<div class="gameNode even" id="node_6"></div>
<div class="gameNode odd" id="node_7"></div>
<div class="gameNode even" id="node_8"></div>
<div class="gameNode odd" id="node_9"></div>
<div class="gameNode even" id="node_10"></div>
</div>
<div id="row_2" class="row">
<div class="gameNode odd" id="node_11"></div>
<div class="gameNode even" id="node_12"></div>
<div class="gameNode odd" id="node_13"></div>
<div class="gameNode even" id="node_14"></div>
<div class="gameNode odd" id="node_15"></div>
</div>
<div id="row_3" class="row">
<div class="gameNode even" id="node_16"></div>
<div class="gameNode odd" id="node_17"></div>
<div class="gameNode even" id="node_18"></div>
<div class="gameNode odd" id="node_19"></div>
<div class="gameNode even" id="node_20"></div>
</div>
<div id="row_4" class="row">
<div class="gameNode odd" id="node_21"></div>
<div class="gameNode even" id="node_22"></div>
<div class="gameNode odd" id="node_23"></div>
<div class="gameNode even" id="node_24"></div>
<div class="gameNode odd" id="node_25"></div>
</div>
</div>
This happens because the default value for grid-auto-columns
(and, ipso facto, grid-template-columns
) is auto
, meaning a single column sized to fit content.
In order to make your layout work using display: inline-grid
, you would need to define columns, which doesn't appear to be acceptable in your layout.
#start {
display: inline-grid;
grid-template-columns: repeat(5, auto);
border: 2px solid red;
}
.row {
display: grid;
grid-template-columns: repeat(auto-fill, 25px);
grid-auto-rows: 25px;
}
.even { background-color: #666; }
.odd { background-color: #999; }
<div id="start">
<div id="row_0" class="row">
<div class="gameNode odd" id="node_1"></div>
<div class="gameNode even" id="node_2"></div>
<div class="gameNode odd" id="node_3"></div>
<div class="gameNode even" id="node_4"></div>
<div class="gameNode odd" id="node_5"></div>
</div>
<div id="row_1" class="row">
<div class="gameNode even" id="node_6"></div>
<div class="gameNode odd" id="node_7"></div>
<div class="gameNode even" id="node_8"></div>
<div class="gameNode odd" id="node_9"></div>
<div class="gameNode even" id="node_10"></div>
</div>
<div id="row_2" class="row">
<div class="gameNode odd" id="node_11"></div>
<div class="gameNode even" id="node_12"></div>
<div class="gameNode odd" id="node_13"></div>
<div class="gameNode even" id="node_14"></div>
<div class="gameNode odd" id="node_15"></div>
</div>
<div id="row_3" class="row">
<div class="gameNode even" id="node_16"></div>
<div class="gameNode odd" id="node_17"></div>
<div class="gameNode even" id="node_18"></div>
<div class="gameNode odd" id="node_19"></div>
<div class="gameNode even" id="node_20"></div>
</div>
<div id="row_4" class="row">
<div class="gameNode odd" id="node_21"></div>
<div class="gameNode even" id="node_22"></div>
<div class="gameNode odd" id="node_23"></div>
<div class="gameNode even" id="node_24"></div>
<div class="gameNode odd" id="node_25"></div>
</div>
</div>
display: inline-flex
With flexbox, a block level container (display: flex
) won't work for the same reason described in the display: grid
section above.
However, display: inline-flex
works because the default value of flex-basis
is auto
, meaning that items are sized to fit content, and, unlike grid layout, there is no default setting forcing the items to stack into a single column.
#start {
display: inline-flex;
border: 2px solid red;
}
.row {
display: grid;
grid-template-columns: repeat(auto-fill, 25px);
grid-auto-rows: 25px;
}
.even { background-color: #666; }
.odd { background-color: #999; }
<div id="start">
<div id="row_0" class="row">
<div class="gameNode odd" id="node_1"></div>
<div class="gameNode even" id="node_2"></div>
<div class="gameNode odd" id="node_3"></div>
<div class="gameNode even" id="node_4"></div>
<div class="gameNode odd" id="node_5"></div>
</div>
<div id="row_1" class="row">
<div class="gameNode even" id="node_6"></div>
<div class="gameNode odd" id="node_7"></div>
<div class="gameNode even" id="node_8"></div>
<div class="gameNode odd" id="node_9"></div>
<div class="gameNode even" id="node_10"></div>
</div>
<div id="row_2" class="row">
<div class="gameNode odd" id="node_11"></div>
<div class="gameNode even" id="node_12"></div>
<div class="gameNode odd" id="node_13"></div>
<div class="gameNode even" id="node_14"></div>
<div class="gameNode odd" id="node_15"></div>
</div>
<div id="row_3" class="row">
<div class="gameNode even" id="node_16"></div>
<div class="gameNode odd" id="node_17"></div>
<div class="gameNode even" id="node_18"></div>
<div class="gameNode odd" id="node_19"></div>
<div class="gameNode even" id="node_20"></div>
</div>
<div id="row_4" class="row">
<div class="gameNode odd" id="node_21"></div>
<div class="gameNode even" id="node_22"></div>
<div class="gameNode odd" id="node_23"></div>
<div class="gameNode even" id="node_24"></div>
<div class="gameNode odd" id="node_25"></div>
</div>
</div>
Answer #3:
You can use display inline-grid to grow the container by its children, but you need to set the number of elements in repeat(5, 25px);
#start {
display: inline-grid;
}
.row {
grid-template-columns: repeat(5, 25px);
}
But one question: for what is it? CSS GRID for two direction, you don't need the div.row, you control all with only the root container. For what you are making, you should use css flex.