Search code examples
cssreactjscss-grid

create dynamic grid layout


My goal is to create nxn tic tac toe game in React. Now I have the board class wrapping squares. This is the css:

.board {
  display: grid;
  width: 25rem;
  height: 25rem;
  **grid-template: repeat(3, 1fr) / repeat(3, 1fr);**
     
}
.square {
  border: 1px solid black;
  display: grid;
  place-items: center;
  font-size: 40px;
}

In the .board css how can I make this dynamic and not 3 - for example if the grid is 4X4 then I will have to do repeat(4,1fr) etc...how it will be generic for all sizes?


Solution

  • UPDATE

    If you specifically want a React solution, I've put together a demo for you here.

    import React, { useState, useEffect, useRef } from "react";
    import "./styles.css";
    
    export default function App() {
      const [gridSize, setGridSize] = useState(4);
      const boardRef = useRef(null);
    
      useEffect(() => {
        boardRef.current.style.setProperty("--grid-size", gridSize);
      }, [gridSize]);
    
      const createSquares = () => {
        let html = [];
        for (let i = 0; i < gridSize * gridSize; i++) {
          html.push(<div key={i} className="square"></div>);
        }
        return html;
      };
    
      function handleClick() {
        setGridSize(gridSize === 4 ? 3 : 4);
      }
    
      return (
        <div className="App">
          <button className="my-button" onClick={handleClick}>
            Toggle grid
          </button>
    
          <div ref={boardRef} className="board">
            {createSquares()}
          </div>
        </div>
      );
    }
    .board {
      --grid-size: 4;
      /* Start with 4x4 */
      display: grid;
      width: 25rem;
      height: 25rem;
      grid-template: repeat(var(--grid-size), 1fr) / repeat(var(--grid-size), 1fr);
    }
    
    .square {
      border: 1px solid black;
      display: grid;
      place-items: center;
      font-size: 40px;
    }
    
    .my-button {
      padding: 1rem;
      position: absolute;
      right: 0;
      top: 0;
    }


    I would use a CSS custom property, which you can set via JavaScript at any time.

    const button = document.querySelector('.my-button');
    
    const board = document.querySelector(".board");
    
    button.addEventListener("click", handleClick);
    
    function handleClick() {
      board.innerHTML = '';
      for (let i = 0; i < 9; i++) {
        board.innerHTML +='<div class="square"></div>';
      }
      board.style.setProperty("--grid-size", 3);
    }
    .board {
      --grid-size: 4; /* Start with 4x4 */
      display: grid;
      width: 25rem;
      height: 25rem;
      grid-template: repeat(var(--grid-size), 1fr) / repeat(var(--grid-size), 1fr);
    }
    
    .square {
      border: 1px solid black;
      display: grid;
      place-items: center;
      font-size: 40px;
    }
    
    .my-button {
      padding: 1rem;
      position: absolute;
      right: 0;
      top: 0;
    }
    <div class="board">
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>  
    </div>
    
    <button class="my-button">
      Change to 3x3
    </button>

    jsFiddle