0

I'm learning React and JavaScript generally via writing chess game and got to some intersting issue with elements changing position depending on whether content is empty or not.

I create simple CodePen to illustrate problem - https://codepen.io/anon/pen/KbGKrX?editors=0010

Clicking on each square will change it content. Problem is that this square will change position, unless all squares in the same row have same content (null or text). Tried with empty strings and spaces instead null and got the same behaviour.

Inspecting in Dev Tools I see no change of CSS so I am puzzled and not sure whether its is some strange behaviour because of React or something else.

I would appreciate any help on this one.

JS part:

const BoardSquare = (props) => {
  return (
      <button
        className={`board-square board-square-${props.squareColor}`}
        onClick={props.onClick}
      >
        {props.piece}
      </button>
  );
};

const squares = new Array(8);
for (let i = 0; i < 8; i++) {
  let row = new Array(8);
  for (let j = 0; j < 8; j++) {
    row[j] = {
      rowIndex: i,
      colIndex: j,
      key: (j + 10).toString(36) + (8 - i).toString(),
      color: (i + j) % 2 === 0 ? "light" : "dark",
      piece: i === 1 ? j : null
    };
  }
  squares[i] = row;
}

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: squares,
      whiteMove: true
    };
  }

  handleClickSquare(i, j) {
    //alert("clicked:" + i + " " + j);
    const squares = this.state.squares.slice();
    squares[i][j].piece = squares[i][j].piece !== null ? null : j;
    this.setState({ squares: squares, whiteMove: !this.state.whiteMove });
  }

    handleClickNewGame() {
    const squares = this.state.squares.slice();
    for (let i = 0; i < 8; i++) {
      squares[1][i].piece = i;
      squares[6][i].piece = i;
    }

    this.setState({ squares: squares, whiteMove: true });
  }



  render() {
    return (
          <div id="board">
            {this.state.squares.map((row, rowIndex) => {
              return (
                <div>{
                row.map((square, colIndex) => {
                return (
                  <BoardSquare
                    key={square.key}
                    squareColor={square.color}
                    id={square.key}
                    piece={square.piece}

                    onClick={() => this.handleClickSquare(rowIndex, colIndex)}
                  />
                );
              })}
              </div>)
            })}
          </div>
    )
  }
}

// ========================================

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);

CSS:

#board {
    font-size: 0;  
}

.board-square {
    text-align: center;
    align-items: center;
    justify-content: center;
    height: 20px;
    width: 20px;
    line-height: 20px;
    font-size: 10px;
    margin: 0;
    padding: 0;
    border: 0;
}

.board-square-dark {
    background-color: green;
}

.board-square-light {
    background-color: #E0AB76;
}
RegEx
  • 125
  • 3
  • 10
  • 2
    Have you tried rendering ` ` when the square is empty? – Chris Jan 14 '19 at 16:45
  • @Christiaan no, I tried normal space in unicode ("\u0020") instead null and it changed nothing. Just now I tried Non-breaking space ("\u00A0") and it does not cause element to move! Thanks! could you provide some short explanation of this so me and others can understand why this happens? – RegEx Jan 14 '19 at 17:09

1 Answers1

1

The reason for this behavior is because of the default baseline vertical alignment. Already well explained in this answer: https://stackoverflow.com/a/13550706/1790728

By changing the display to inline-block and setting vertical-align to top, the squares will be aligned without using a white-space.

Working example: https://codepen.io/anon/pen/MZLZYj

Chris
  • 6,331
  • 1
  • 21
  • 25