Mouse click hitbox offset on play board after responsive layout shift
Summary
On the Maia Chess play page, piece selection is horizontally offset from the visible board. Clicking near the right edge of G2 selects H2 instead. The visual board and pieces are rendered correctly — only the mouse coordinate mapping is wrong.
The issue disappears after zooming in or out in the browser, which confirms that Chessground's cached board bounds are stale and get corrected only when a resize event forces recalculation.
The bug also appears mid-game: clicks may work correctly at game start, then become wrong after the opponent's first response.
Affected page
Steps to reproduce
- Open the Maia play page on desktop as White.
- Wait for the board and side panels to fully render.
- Click the right edge of the pawn on
G2 (near the G/H boundary).
- Observe that
H2 is selected instead of G2.
- Zoom in or out in the browser — selection now works correctly.
Note: This scenario is timing-sensitive. A hard refresh may be required multiple times before the layout shift window is hit and the bug manifests.
Or (more reliably reproducible):
- Start a game as White.
- Make a move.
- Wait for the opponent response.
- Click the right edge of any piece — wrong square is selected.
- Zoom in or out in the browser — selection now works correctly.
Note: In this scenario, the horizontal offset is likely triggered by the FEN update after the first move, which causes the board to shift in the flex layout.
The offset affects all squares. To notice the problem, click the right edge of any piece's square — the click will resolve to the square immediately to the right.
Root cause
Chessground caches board bounds lazily via a memoized getBoundingClientRect(). The cache is invalidated on window.resize or scroll, and re-populated on the next bounds() call — which happens during piece rendering and on user interactions.
At page load: Chessground initializes and caches bounds before the responsive flex layout finishes settling. The board shifts, but the cache is not cleared.
After each move: React re-renders the Fen, stats panel, move list, and other components. If a sibling panel changes width, the flex row reflows and the board shifts position — but Chessground's bounds cache still holds the old coordinates. The next user click then maps to the wrong square.
In both cases, bounds.left no longer matches the board's actual position, and clicks land on the wrong square.
Mouse click hitbox offset on play board after responsive layout shift
Summary
On the Maia Chess play page, piece selection is horizontally offset from the visible board. Clicking near the right edge of
G2selectsH2instead. The visual board and pieces are rendered correctly — only the mouse coordinate mapping is wrong.The issue disappears after zooming in or out in the browser, which confirms that Chessground's cached board bounds are stale and get corrected only when a resize event forces recalculation.
The bug also appears mid-game: clicks may work correctly at game start, then become wrong after the opponent's first response.
Affected page
Steps to reproduce
G2(near the G/H boundary).H2is selected instead ofG2.Or (more reliably reproducible):
The offset affects all squares. To notice the problem, click the right edge of any piece's square — the click will resolve to the square immediately to the right.
Root cause
Chessground caches board bounds lazily via a memoized
getBoundingClientRect(). The cache is invalidated onwindow.resizeor scroll, and re-populated on the nextbounds()call — which happens during piece rendering and on user interactions.At page load: Chessground initializes and caches bounds before the responsive flex layout finishes settling. The board shifts, but the cache is not cleared.
After each move: React re-renders the Fen, stats panel, move list, and other components. If a sibling panel changes width, the flex row reflows and the board shifts position — but Chessground's bounds cache still holds the old coordinates. The next user click then maps to the wrong square.
In both cases,
bounds.leftno longer matches the board's actual position, and clicks land on the wrong square.