CSS Grid with evenly distributed cells for board game (square)

ghz 8months ago ⋅ 88 views

I am trying to create a simple board game UI using css grid. I assumed this would be the perfect tool for the purpose however I am not able to achieve the desired results, namely:

1 - The tiles will auto size so that they fill the parent 2 - The tiles will maintain a 1:1 aspect ratio 3 - The page content should NOT expand outside of the visible browser window.

Unfortunately every solution I've tried so far either causes overflow, or the page extending horizontally when the height of each tile gets too big (or vertically when the width of each tile gets too big).

:root
        {
            --col_and_row_count: 10;
        }

        .main 
        {
            display: grid;
            grid-template-rows: 60px 1fr 60px; 
            gap: 1em;
            height: 100vh;
        }

        .wrapper 
        {
            display: grid;
            grid-template-columns: 200px 1fr;
        }

        .board 
        {
            display: flex;
            align-items: center;
        }

        .tiles 
        {
            margin: auto;
            display: grid;
            grid-template-columns: repeat(var(--col_and_row_count), 1fr);
            gap: 12px;
            aspect-ratio: 1; 
        }

        .tiles > div 
        {
            background: green;
               
        }
 <div class="main">

        <div>
            Some heading text goes here
        </div>

        <div class="wrapper">

            <div>
                The side bar goes here
            </div>


            <div class="board">

                <div class="tiles">
                    <div data-tile-index="0"></div>
                    <div data-tile-index="1"></div>
                    <div data-tile-index="2"></div>
                    <div data-tile-index="3"></div>
                    <div data-tile-index="4"></div>
                    <div data-tile-index="5"></div>
                    <div data-tile-index="6"></div>
                    <div data-tile-index="7"></div>
                    <div data-tile-index="8"></div>
                    <div data-tile-index="9"></div>
                    <div data-tile-index="10"></div>
                    <div data-tile-index="11"></div>
                    <div data-tile-index="12"></div>
                    <div data-tile-index="13"></div>
                    <div data-tile-index="14"></div>
                    <div data-tile-index="15"></div>
                    <div data-tile-index="16"></div>
                    <div data-tile-index="17"></div>
                    <div data-tile-index="18"></div>
                    <div data-tile-index="19"></div>
                    <div data-tile-index="20"></div>
                    <div data-tile-index="21"></div>
                    <div data-tile-index="22"></div>
                    <div data-tile-index="23"></div>
                    <div data-tile-index="24"></div>
                    <div data-tile-index="25"></div>
                    <div data-tile-index="26"></div>
                    <div data-tile-index="27"></div>
                    <div data-tile-index="28"></div>
                    <div data-tile-index="29"></div>
                    <div data-tile-index="30"></div>
                    <div data-tile-index="31"></div>
                    <div data-tile-index="32"></div>
                    <div data-tile-index="33"></div>
                    <div data-tile-index="34"></div>
                    <div data-tile-index="35"></div>
                    <div data-tile-index="36"></div>
                    <div data-tile-index="37"></div>
                    <div data-tile-index="38"></div>
                    <div data-tile-index="39"></div>
                    <div data-tile-index="40"></div>
                    <div data-tile-index="41"></div>
                    <div data-tile-index="42"></div>
                    <div data-tile-index="43"></div>
                    <div data-tile-index="44"></div>
                    <div data-tile-index="45"></div>
                    <div data-tile-index="46"></div>
                    <div data-tile-index="47"></div>
                    <div data-tile-index="48"></div>
                    <div data-tile-index="49"></div>
                    <div data-tile-index="50"></div>
                    <div data-tile-index="51"></div>
                    <div data-tile-index="52"></div>
                    <div data-tile-index="53"></div>
                    <div data-tile-index="54"></div>
                    <div data-tile-index="55"></div>
                    <div data-tile-index="56"></div>
                    <div data-tile-index="57"></div>
                    <div data-tile-index="58"></div>
                    <div data-tile-index="59"></div>
                    <div data-tile-index="60"></div>
                    <div data-tile-index="61"></div>
                    <div data-tile-index="62"></div>
                    <div data-tile-index="63"></div>
                    <div data-tile-index="64"></div>
                    <div data-tile-index="65"></div>
                    <div data-tile-index="66"></div>
                    <div data-tile-index="67"></div>
                    <div data-tile-index="68"></div>
                    <div data-tile-index="69"></div>
                    <div data-tile-index="70"></div>
                    <div data-tile-index="71"></div>
                    <div data-tile-index="72"></div>
                    <div data-tile-index="73"></div>
                    <div data-tile-index="74"></div>
                    <div data-tile-index="75"></div>
                    <div data-tile-index="76"></div>
                    <div data-tile-index="77"></div>
                    <div data-tile-index="78"></div>
                    <div data-tile-index="79"></div>
                    <div data-tile-index="80"></div>
                    <div data-tile-index="81"></div>
                    <div data-tile-index="82"></div>
                    <div data-tile-index="83"></div>
                    <div data-tile-index="84"></div>
                    <div data-tile-index="85"></div>
                    <div data-tile-index="86"></div>
                    <div data-tile-index="87"></div>
                    <div data-tile-index="88"></div>
                    <div data-tile-index="89"></div>
                    <div data-tile-index="90"></div>
                    <div data-tile-index="91"></div>
                    <div data-tile-index="92"></div>
                    <div data-tile-index="93"></div>
                    <div data-tile-index="94"></div>
                    <div data-tile-index="95"></div>
                    <div data-tile-index="96"></div>
                    <div data-tile-index="97"></div>
                    <div data-tile-index="98"></div>
                    <div data-tile-index="99"></div>
                </div>



            </div>

        </div>



        <div>
            This is the footer
        </div>




    </div>

Run code snippet

Answers

To achieve your desired results with CSS Grid, you can make a few adjustments to your existing code:

  1. Auto-sizing tiles: You can use the grid-auto-columns property to automatically size the columns of the grid so that they fill the parent container.

  2. Maintain 1:1 aspect ratio: Since CSS Grid does not have a built-in way to maintain aspect ratio, you can use a trick by setting the padding-top or padding-bottom of each tile to a percentage value. This way, the height of each tile will be determined by its width, maintaining a 1:1 aspect ratio.

  3. Prevent content overflow: You can ensure that the content does not overflow outside of the visible browser window by setting overflow: hidden on the body or the parent container.

Here's the updated CSS and HTML:

:root {
  --col_and_row_count: 10;
}

.main {
  display: grid;
  grid-template-rows: 60px 1fr 60px;
  gap: 1em;
  height: 100vh;
  overflow: hidden; /* Prevent content overflow */
}

.wrapper {
  display: grid;
  grid-template-columns: 200px 1fr;
}

.board {
  display: flex;
  align-items: center;
}

.tiles {
  display: grid;
  grid-template-columns: repeat(var(--col_and_row_count), 1fr);
  gap: 12px;
}

.tiles > div {
  background: green;
  padding-top: 100%; /* Maintain 1:1 aspect ratio */
}

.tiles > div[data-tile-index="0"] { /* Example: Set different styles for specific tiles */
  background: red;
}
<div class="main">
  <div>
    Some heading text goes here
  </div>
  <div class="wrapper">
    <div>
      The side bar goes here
    </div>
    <div class="board">
      <div class="tiles">
        <!-- Your tile elements here -->
        <!-- Example: -->
        <div data-tile-index="0"></div>
        <div data-tile-index="1"></div>
        <!-- Add more tiles as needed -->
      </div>
    </div>
  </div>
  <div>
    This is the footer
  </div>
</div>

With these adjustments, the tiles should auto-size to fill the parent container, maintain a 1:1 aspect ratio, and prevent content overflow outside of the visible browser window.