5

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:

enter image description here

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?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
supafiya
  • 137
  • 2
  • 9

3 Answers3

4

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:

enter image description here

#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.

enter image description here

#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 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.

enter image description here

#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.

enter image description here

#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>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    Thanks, this helped a lot. although I decided to go with a table instead, but this gives a lot of information I didn't know. – supafiya Jul 29 '19 at 04:19
  • 2
    This is an excellent and comprehensive answer which helped me fix my similar issue (I used the inline-grid solution). Thanks! – ccbunney Sep 04 '20 at 13:11
0

Try using margin-left and margin-right properties to bring in the width a bit. Also you could try using a percentage for the with (something below 100%). Since you have content centered that might bring your box off the left and right edges.

Austin_K
  • 58
  • 7
  • Percentage based width does not help, this is what happens https://imgur.com/3ZM4slq – supafiya Jul 26 '19 at 20:11
  • Could you clarify your end goal in a different way? Is it that you just want a box that is a height of 125px with an equal width? – Austin_K Jul 26 '19 at 20:20
0

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.

  • well, I'm making a grid so I thought grid would be better. I'll try flex. I also can't set the repeat amount because the grid count is a variable. thanks – supafiya Jul 26 '19 at 22:21