Call Anytime 24/7
Mail Us For Support
Office Address
Lahore, Punjab, Pakistan
Creating games in the browser is a great way to strengthen your front-end skills. In this tutorial, we’ll walk through building a fully functional Chess game using HTML, CSS, and JavaScript, enhanced with:
Whether you’re a beginner looking to sharpen your skills or a seasoned dev exploring game mechanics in JavaScript, this post will guide you step by step.
To follow along, you should have:
Create a new folder and add three files:
/chess-game
├── index.html
├── style.css
└── script.js
This file sets up the structure of the chessboard, timers, captured pieces, and includes the required scripts.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Chess Game</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.12.0/chess.min.js"></script>
</head>
<body>
<h1>Chess Game</h1>
<div id="info">
<div id="turn">Turn: White</div>
<div id="timers">
<span>White: <span id="white-timer">00:00</span></span>
<span>Black: <span id="black-timer">00:00</span></span>
</div>
</div>
<div id="captured">
<div>White Captured: <span id="white-captured"></span></div>
<div>Black Captured: <span id="black-captured"></span></div>
</div>
<div id="chessboard"></div>
<audio id="moveSound" src="https://www.soundjay.com/button/beep-07.wav" preload="auto"></audio>
<script src="script.js"></script>
</body>
</html>
Here’s how we’ll visually structure the board and elements:
body {
display: flex;
flex-direction: column;
align-items: center;
background: #f5f5f5;
font-family: sans-serif;
margin: 0;
padding: 0;
}
h1 {
margin: 20px;
}
#info {
display: flex;
justify-content: space-between;
width: 400px;
margin-bottom: 10px;
}
#timers {
display: flex;
gap: 20px;
}
#captured {
display: flex;
justify-content: space-around;
width: 400px;
margin-bottom: 10px;
}
#chessboard {
display: grid;
grid-template-columns: repeat(8, 60px);
grid-template-rows: repeat(8, 60px);
border: 2px solid #333;
}
.square {
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
cursor: pointer;
}
.white {
background-color: #f0d9b5;
}
.black {
background-color: #b58863;
}
.highlight {
background-color: yellow !important;
}
.piece {
user-select: none;
}
Here’s where the magic happens — handling move validation, UI updates, and game logic using chess.js.
const board = document.getElementById('chessboard');
const chess = new Chess();
const moveSound = document.getElementById('moveSound');
const whiteCaptured = document.getElementById('white-captured');
const blackCaptured = document.getElementById('black-captured');
const turnText = document.getElementById('turn');
const whiteTimer = document.getElementById('white-timer');
const blackTimer = document.getElementById('black-timer');
let selectedSquare = null;
let highlightedSquares = [];
let whiteTime = 0;
let blackTime = 0;
// Unicode symbols for pieces
const pieceUnicode = {
pw: '♙', nw: '♘', bw: '♗', rw: '♖', qw: '♕', kw: '♔',
pb: '♟', nb: '♞', bb: '♝', rb: '♜', qb: '♛', kb: '♚'
};
// Format seconds into mm:ss
function formatTime(sec) {
const m = Math.floor(sec / 60).toString().padStart(2, '0');
const s = (sec % 60).toString().padStart(2, '0');
return `${m}:${s}`;
}
// Update timers
setInterval(() => {
if (chess.turn() === 'w') whiteTime++;
else blackTime++;
whiteTimer.textContent = formatTime(whiteTime);
blackTimer.textContent = formatTime(blackTime);
}, 1000);
// Clear move highlights
function clearHighlights() {
highlightedSquares.forEach(sq => sq.classList.remove('highlight'));
highlightedSquares = [];
}
// Draw board
function createBoard() {
board.innerHTML = '';
clearHighlights();
const boardArr = chess.board();
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const square = document.createElement('div');
square.classList.add('square');
square.classList.add((row + col) % 2 === 0 ? 'white' : 'black');
const file = 'abcdefgh'[col];
const rank = 8 - row;
const pos = file + rank;
square.dataset.position = pos;
const piece = boardArr[row][col];
if (piece) {
const symbol = pieceUnicode[piece.type + piece.color];
square.textContent = symbol || '';
square.classList.add('piece');
}
square.addEventListener('click', () => handleClick(square, pos));
board.appendChild(square);
}
}
turnText.textContent = `Turn: ${chess.turn() === 'w' ? 'White' : 'Black'}`;
}
// Handle click on square
function handleClick(square, position) {
const piece = chess.get(position);
if (selectedSquare && chess.moves({ square: selectedSquare }).includes(position)) {
const move = chess.move({ from: selectedSquare, to: position });
if (move) {
moveSound.play();
// Handle captured pieces
if (move.captured) {
const capturedSymbol = pieceUnicode[move.captured + (move.color === 'w' ? 'b' : 'w')];
if (move.color === 'w') {
blackCaptured.textContent += capturedSymbol;
} else {
whiteCaptured.textContent += capturedSymbol;
}
}
selectedSquare = null;
createBoard();
}
} else if (piece && piece.color === chess.turn()) {
selectedSquare = position;
clearHighlights();
const moves = chess.moves({ square: position, verbose: true });
moves.forEach(m => {
const sq = document.querySelector(`[data-position='${m.to}']`);
if (sq) {
sq.classList.add('highlight');
highlightedSquares.push(sq);
}
});
} else {
selectedSquare = null;
clearHighlights();
}
}
// Initialize
createBoard();
Feature | Description |
♟ Move Validation | Enforced using chess.js |
🔁 Turn Logic | Automatically swaps turns between players |
✨ Highlight Moves | Shows valid moves on click |
🕒 Timer | Real-time timer for each player |
💥 Capture Display | Captured pieces shown with Unicode |
🔊 Sound | Simple move sound on valid move |
Here are some improvements you can add:
This project is a fantastic example of blending JavaScript game logic with interactive UI to create a complete, playable browser game. By leveraging chess.js for validation and combining HTML/CSS for UI, we built a polished chess game entirely in the browser.
If you found this tutorial helpful, feel free to share it, leave a comment, or suggest the next feature to add!