2

I'm building a game which has the board on the left and the score area on the right. I'd like the individual tiles on the board to remain squares as the browser is expanded. As of now they grow width-wise but they don't grow in height.

Starting set up:

before expansion

But after making the window wider the tiles become rectangular: after expansion

How can I keep the tiles as squares when the browser window is resized?

Here's the relevant part of .html file:

<div class="board">
    <div class="square" id="square1">5</div>
    (...and 15 more like the above line...)
</div>
    
<div class="score">
    <h1>Score:</h1>
    <h2>0</h2>
</div>

JavaScript function that draws the tiles/squares:

function drawSquares() {
    for(let i = 1; i < 17; i++) {
        const square = document.createElement('div')
        square.setAttribute('class', 'square')
        square.setAttribute('id', ('square'+i))
        square.innerText = randArr[i-1]
        board.appendChild(square)
    }
}

and my full CSS as I'm not sure which part(s) to change:

body {
    display: flex;
}

.board {
    height: 370px;
    width: 70%;
    display: flex;
    flex-wrap: wrap;
    background-color: rgb(172, 170, 170);
    padding: 1%; 
    margin: 1%;
}

.score {
    background-color: rgb(172, 170, 170);
    margin: 1%;
    width: 30%;
} 

.square {
    height: 23%;
    width: 23%;
    background-color: rgb(121, 120, 117);
    margin-left: 1%;
    margin-right: 1%;
    justify-content: center;
    align-items: center;
    font-size: 5vh;
    color: rgb(121, 120, 117);
}

h1, h2 {
    text-align: center;
}

(The .square CSS selector styles the tiles)

FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
Tzvi2
  • 182
  • 3
  • 14
  • 2
    Please show us *all* of the relevant HTML - you haven't included the squares that are the thing you are having the problem with! – FluffyKitten Aug 27 '20 at 03:01
  • Good catch. The squares were added with JS so I forgot to add them here. I've updated the post... – Tzvi2 Aug 27 '20 at 03:04
  • You can include the js that creates them. It makes it easier to help if you give us a [minimal,reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) with all the relevant code (either the JS or the HTML that it generates) so that we can actually see the problem. Also, can you let us know if these squares will contain anything, and if so, what? – FluffyKitten Aug 27 '20 at 03:09
  • Just added the JS. The squares each contain one number between one and eight. The numbers are revealed (by changing their color) when clicking on squares. – Tzvi2 Aug 27 '20 at 03:14

2 Answers2

1

Forcing a square (or any other) aspect ratio(s) of dynamically sized elements is one of the most difficult problems to solve with pure CSS. It is probably easier to use javascript to ensure the width/height ratio of the board element stays 1:1.

It would probably look something like this:

// Your example uses a class called board so maybe change it to an id or write your own js here:
let board = document.getElementById('board');

// Get width or height of board, whichever is smallest.
let size = Math.min(board.scrollHeight, board.scrollWidth);

// Set size of board.
board.style.width = size + 'px';
board.style.height = size + 'px';

Note that the above code snippet does not run again when the window is resized so you might want to put the board inside a container that grows to the maximum available space and take the smallest dimension of that and wrap the JS in a window.onresize event-listener.

Matt
  • 699
  • 5
  • 15
1

To keep the aspect ratio in a responsive design, using the same height as width doesn't work as you saw. Height depends on the containing block having an explicit height set, but in a responsive grid, we don't want a fixed height.

Instead, you can use the padding as it will calculate the % of the container in the same way as the width. You can change the .square class to this:

.square {
    width: 23%;
    height:0;
    padding-bottom: 23%;
    /* Rest of your CSS... */
}

What this does:

  • We can set the padding-bottom to the same as the width - 23% in this case - to make the square
  • Set the height to 0 so that the padding-bottom is the only thing that is adding height

This gives you a fully responsive grid that keeps the same aspect ratio no matter what size the screen is.

Working Snippet:

function drawSquares() {
    for(let i = 1; i < 17; i++) {    
        const square = document.createElement('div')
        square.setAttribute('class', 'square')
        square.setAttribute('id', ('square'+i))
        square.innerText = [i];
        board = document.getElementsByClassName('board')
        board[0].appendChild(square)
    }
}
drawSquares();
body {
    display: flex;
}

.board {
    height: auto;
    width: 70%;
    display: flex;
    flex-wrap: wrap;
    background-color: rgb(172, 170, 170);
    padding: 1%; 
    margin: 1%;
}

.score {
    background-color: rgb(172, 170, 170);
    margin: 1%;
    width: 30%;
} 

.square {
    width: 23%;
    height:0;
    padding-bottom: 23%;
    background-color: rgb(121, 120, 117);
    margin-left: 1%;
    margin-right: 1%;
    margin-bottom: 2%;
    justify-content: center;
    align-items: center;
    font-size: 5vh;
    color: rgb(121, 120, 117);
    color: #fff;
}

h1, h2 {
    text-align: center;
}
<div class="board">
</div>
    
<div class="score">
    <h1>Score:</h1>
    <h2>0</h2>
</div>

In the example above, I also:

  • removed the height: 370px; fron your .board as it wasn't growing with the squares
  • added a bottom margin to the .squares to keep the spacing even
  • made the numbers white so I could verify that they didn't affect the size
FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
  • I like your idea of using padding this way but the code snippet does not seem to work for me (firefox on linux) – Matt Aug 27 '20 at 03:28
  • @Matt Thanks for your comment - I'd accidentally deleted the width from the css for the square! Duh! I've edited my answer to add it back :) – FluffyKitten Aug 27 '20 at 03:33
  • Thank you! Appreciate the explanation and working code! – Tzvi2 Aug 27 '20 at 03:42