0

So I was writing this basic tictactoe game, and in the process I've made a grid using a container (display:flex) and 9 elements with class of 'cell' inside them. Now I want to update the innerHTML of the div that gets clicked. But when I do so, the size of the div gets a little larger. I've seen other people ask this question before in here too, like this Div element moves when changing the innerHTML. They all suggest using vertical-align: top/bottom; to the main container.

I've tried doing this but that doesn't seem to work, in my case. When all the divs are filled up with text, the dimensions go back to normal again. SO it's definitely a problem with empty divs only. Any help?

function game(e) {
  const local = document.getElementById(`${e.id}`);
  local.innerHTML = 'X';
  console.log(e.id);
}
body {
  margin: 0;
  padding: 0;
}

#container {
  width: 420px;
  height: 420px;
  display: flex;
  flex-wrap: wrap;
  background: pink;
  margin-top: 20px;
  margin-left: 20%;
  vertical-align: top;
}

.cell {
  flex: 1;
  margin: 6px;
  min-width: 30%;
  max-height: 30%;
  background: white;
}
<div id='container'>
  <div id='1' class='cell' onClick='game(this)'></div>
  <div id='2' class='cell' onClick='game(this)'></div>
  <div id='3' class='cell' onClick='game(this)'></div>
  <div id='4' class='cell' onClick='game(this)'></div>
  <div id='5' class='cell' onClick='game(this)'></div>
  <div id='6' class='cell' onClick='game(this)'></div>
  <div id='7' class='cell' onClick='game(this)'></div>
  <div id='8' class='cell' onClick='game(this)'></div>
  <div id='9' class='cell' onClick='game(this)'></div>
</div>

I also tried adding a wide space to all the elements just so that they aren't empty anymore.

for(let i=1; i<10;i++)
  document.getElementById(`${i}`).innerHTML=' ';

That didn't help either, and moreover I don't exactly prefer using this even if it would have worked. Looking for a seamless solution.

Note: I've been doing html and javascript for 2 months only, so not exactly superior with coding and/or syntax. Any criticism would be helpful.

Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32
Adil Ahmed
  • 395
  • 1
  • 11

4 Answers4

1

Here you don't need your cells to change size, you want them to be 30% of the grid (in height and width) all the time.

Just use width and height instead of max-width and min-width.

And remove flex: 1;

function game(e) {
  const local = document.getElementById(`${e.id}`);
  local.innerHTML = 'X';
  console.log(e.id);
}
body {
  margin: 0;
  padding: 0;
}

#container {
  width: 420px;
  height: 420px;
  display: flex;
  flex-wrap: wrap;
  background: pink;
  margin-top: 20px;
  margin-left: 20%;
  vertical-align: top;
}

.cell {
  margin: 6px;
  width: 30%;
  height: 30%;
  background: white;
}
<div id="container">
  <div id="1" class="cell" onClick="game(this)"></div>
  <div id="2" class="cell" onClick="game(this)"></div>
  <div id="3" class="cell" onClick="game(this)"></div>
  <div id="4" class="cell" onClick="game(this)"></div>
  <div id="5" class="cell" onClick="game(this)"></div>
  <div id="6" class="cell" onClick="game(this)"></div>
  <div id="7" class="cell" onClick="game(this)"></div>
  <div id="8" class="cell" onClick="game(this)"></div>
  <div id="9" class="cell" onClick="game(this)"></div>
</div>
tamarin
  • 549
  • 4
  • 12
  • Perfect. But I have a question, still. If I do this, then what was the point of applying display-flex, to the container? – Adil Ahmed Jun 06 '20 at 11:25
  • Oh wait, I think my limited understanding of the working principle of flex itself made it clumsy. This is the perfect solution that I was looking for, so thank you. – Adil Ahmed Jun 06 '20 at 11:26
  • Flex is perfect here to design this layout easily, but true, you could do that another way. – tamarin Jun 06 '20 at 11:33
  • Yes. But I did not know when/where to use this flex: 1; property. Hence the problem. I could have used potentially other solutions, but I'm trying to understand flex more and more and get used to it. I used inline-block and border box in my [Etch-A-Sketch project](https://adil-bub.github.io/Etch-A-Sketch/), to make a grid. But flex definitely seems more straightforward. – Adil Ahmed Jun 06 '20 at 11:40
  • @Adil This project looks nice. What's the goal behind it? – tamarin Jun 08 '20 at 13:29
  • Aye thanks man. Actually it was an exercise given by [The Odin Project](https://www.theodinproject.com) to get students more and more used to DOM manipulation using javascript. It is more of a basic javascript project. – Adil Ahmed Jun 09 '20 at 14:13
0

One possible fix would be to put in a &nbsp; in each at the start

function game(e) {
  const local = document.getElementById(`${e.id}`);
  local.innerHTML = 'X';
  console.log(e.id);
}
body {
  margin: 0;
  padding: 0;
}

#container {
  width: 420px;
  height: 420px;
  display: flex;
  flex-wrap: wrap;
  background: pink;
  margin-top: 20px;
  margin-left: 20%;
  vertical-align: top;
}

.cell {
  flex: 1;
  margin: 6px;
  min-width: 30%;
  max-height: 30%;
  background: white;
}
<div id='container'>
  <div id='1' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='2' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='3' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='4' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='5' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='6' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='7' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='8' class='cell' onClick='game(this)'>&nbsp;</div>
  <div id='9' class='cell' onClick='game(this)'>&nbsp;</div>
</div>

Since you are using a "grid" you can also use css grid, visually you can set the sizes as you wish here but this is an example of that:

const rootElement = document.getElementById('container');
const containerChars = JSON.parse(rootElement.dataset.chars);
const cells = rootElement.getElementsByClassName('cell');

function game() {
  let c = rootElement.dataset.charLast == containerChars[0] ? containerChars[1] : containerChars[0];
  rootElement.dataset.charLast = c;
  this.innerHTML = c;
}

for (let i = 0; i < cells.length; i++) {
  cells[i].onclick = game;
}
body {
  margin: 0;
  padding: 0;
}

#container {
  border: solid 2px #dddddd;
  display: grid;
  grid-template-columns: repeat(3, minmax(2em, 1fr));
  grid-template-rows: repeat(3, minmax(2em, 1fr));
  background: #FFCCDD;
  grid-gap: 0.25rem;
}

.cell {
  background: #ddEEFF;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.75em;
}
<div id='container' data-char-last="X" data-chars='["X","O"]'>
  <div id='1' class='cell'></div>
  <div id='2' class='cell'></div>
  <div id='3' class='cell'></div>
  <div id='4' class='cell'></div>
  <div id='5' class='cell'></div>
  <div id='6' class='cell'></div>
  <div id='7' class='cell'></div>
  <div id='8' class='cell'></div>
  <div id='9' class='cell'></div>
</div>
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • You don't need to use a hack here. The css properties were misused. – tamarin Jun 06 '20 at 10:30
  • Not really a hack, just another option – Mark Schultheiss Jun 06 '20 at 10:31
  • I understand and it's working, but I think it's better to remove what created the problem than using a medicine. – tamarin Jun 06 '20 at 10:34
  • @MarkSchultheiss I do understand what you did here, but I mostly wanted to know what the problem was first rather than jumping to a fix, right away. And moreover as i mentioned I wanted to keep the innerHTML empty and still maintain dimensional consistency. But yes, yours works but as tamarin said, the css was misused in my original situation. Thank you for your time, still. – Adil Ahmed Jun 06 '20 at 11:30
  • I also added a `grid` example – Mark Schultheiss Jun 06 '20 at 13:05
  • @MarkSchultheiss In this situation, I believe grid works perfectly too. So that definitely is another option. But what if I had a table whose flex direction was along rows, and I had to make the thing responsive. Then all I used to do was just change the flex direction to column. But how can I do the same thing, using a grid? I'm sure it's possible, but I'm not exactly aware, how. Hence asking. – Adil Ahmed Jun 07 '20 at 02:44
  • Well, responsive is anther question but just use a `minmax` and autofit `display: grid; grid-template-columns: repeat(auto-fit, minmax(50px, 1fr)); grid-gap: 1rem;` I edited a bit to show the 3X3 grid without your container size large as you had it – Mark Schultheiss Jun 08 '20 at 11:33
-1

Your problem css. Try...

.cell {
    /* flex: 1; */
    /* margin: 6px; */
    min-width: 32.9%;
    /* max-height: 30%; */
    background: white;
    border: 1px solid;
    height: 32.9%;
}
engin
  • 39
  • 5
  • I can make it work, using this. But 32.9% doesn't work, 30% is better. But I do prefer tamarin's solution above. Regardless, thank you for contributing. – Adil Ahmed Jun 06 '20 at 11:23
-1

try adding this line to your css:

* {
    box-sizing: border-box;
}
arnavpanwar99
  • 377
  • 2
  • 6
  • Nope. This doesn't seem to work. My original css was a mess, and that lead to the problem. It all seems to be fine, thanks to @tamarin's solution. – Adil Ahmed Jun 06 '20 at 11:35