In this article, we will learn how to make Tic Tac Toe by just using HTML, CSS, and JavaScript. I’ll explain step by step all of its components that we have to work upon. I firmly believe that working on projects is the best way to learn something. Not only you will be able to easily make this game but also you can play it with your friends. This game is designed in such a way that it runs on all systems including tablets and mobiles. Which will enable it to run without any hassle on any device.
All the related assets, other resources, and the complete HTML, CSS, and JS will be provided at the end of this article.
Creating Initial Files
So we’ll begin with creating a new file namely index.html in VS Code. After that, we have to simply put the boilerplate code. There we will give the title as Tic Tac Toe.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tic Tac Toe</title>
</head>
<body>
</body>
</html>
Now before moving to the next step of writing code make sure to download Live Server. What it does is that when you will right-click onto your code and select the option ‘live Server’ it will show the live preview of your code in a new tab.
In the next step, we will create the navbar and add a link in between. Suppose that link is ‘MyTicTacToe.com’. Secondly, we’ll create a style sheet, and thirdly we will ad a script namely script.js.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<nav>
<ul>
<li>MyTicTacToe.com</li>
</ul>
</nav>
<script src="script.js"></script>
</body>
</html>
At the same time, we will create two new files i.e. style.css and script.js
Game Skeleton & Styling
Now moving ahead we’ll create a game container in HTML and then we design it further in CSS. We have to create two sections as left and right where the main game and game info will be displayed respectively.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<nav>
<ul>
<li>MyTicTacToe.com</li>
</ul>
</nav>
<div class="gameContainer">
<div class="container">
<div class="line"></div>
<div class="box bt-0 bl-0"><span class="boxtext">X</span></div>
<div class="box bt-0"><span class="boxtext">X</span></div>
<div class="box bt-0 br-0"><span class="boxtext">X</span></div>
<div class="box bl-0"><span class="boxtext">X</span></div>
<div class="box"><span class="boxtext">X</span></div>
<div class="box br-0"><span class="boxtext">X</span></div>
<div class="box bl-0 bb-0"><span class="boxtext">X</span></div>
<div class="box bb-0"><span class="boxtext">X</span></div>
<div class="box bb-0 br-0"><span class="boxtext">X</span></div>
</div>
<div class="gameInfo">
<h1>Welcome to Tic Tac MyTicTacToe</h1>
<div>
<span class="info">Turn for X</span>
<button id="reset">Reset</button>
</div>
<div class="imgbox">
<img src="excited.gif" alt="" />
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
JavaScript Logic
Now moving to the next step we’ll eliminate all the X that we have taken earlier and will proceed towards its further designing through Javascript. The major thing that we have to set here is the alternate appearance of X and 0 and along with that, we have to attach audio for Clicks and Game Over(provided at the end) and the exciting gif.
Complete JavaScript
console.log("Welcome to Tic Tac Toe")
let music = new Audio("music.mp3")
let audioTurn = new Audio("ting.mp3")
let gameover = new Audio("gameover.mp3")
let turn = "X"
let isgameover = false;
// Function to change the turn
const changeTurn = ()=>{
return turn === "X"? "0": "X"
}
// Function to check for a win
const checkWin = ()=>{
let boxtext = document.getElementsByClassName('boxtext');
let wins = [
[0, 1, 2, 5, 5, 0],
[3, 4, 5, 5, 15, 0],
[6, 7, 8, 5, 25, 0],
[0, 3, 6, -5, 15, 90],
[1, 4, 7, 5, 15, 90],
[2, 5, 8, 15, 15, 90],
[0, 4, 8, 5, 15, 45],
[2, 4, 6, 5, 15, 135],
]
wins.forEach(e =>{
if((boxtext[e[0]].innerText === boxtext[e[1]].innerText) && (boxtext[e[2]].innerText === boxtext[e[1]].innerText) && (boxtext[e[0]].innerText !== "") ){
document.querySelector('.info').innerText = boxtext[e[0]].innerText + " Won"
isgameover = true
document.querySelector('.imgbox').getElementsByTagName('img')[0].style.width = "200px";
document.querySelector(".line").style.transform = `translate(${e[3]}vw, ${e[4]}vw) rotate(${e[5]}deg)`
document.querySelector(".line").style.width = "20vw";
}
})
}
// Game Logic
// music.play()
let boxes = document.getElementsByClassName("box");
Array.from(boxes).forEach(element =>{
let boxtext = element.querySelector('.boxtext');
element.addEventListener('click', ()=>{
if(boxtext.innerText === ''){
boxtext.innerText = turn;
turn = changeTurn();
audioTurn.play();
checkWin();
if (!isgameover){
document.getElementsByClassName("info")[0].innerText = "Turn for " + turn;
}
}
})
})
// Add onclick listener to reset button
reset.addEventListener('click', ()=>{
let boxtexts = document.querySelectorAll('.boxtext');
Array.from(boxtexts).forEach(element => {
element.innerText = ""
});
turn = "X";
isgameover = false
document.querySelector(".line").style.width = "0vw";
document.getElementsByClassName("info")[0].innerText = "Turn for " + turn;
document.querySelector('.imgbox').getElementsByTagName('img')[0].style.width = "0px"
})
Adding Responsiveness
So our Tic Tac Toe is responsive quite enough till 850×850 but not below that. In order to tackle this, we need to add a CSS media query which is a very simple step. We’ll add that media query in our style sheet by keeping the width at 950. You can click here to know how to do that.
Complete HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tic Tac Toe</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<nav>
<ul>
<li>MyTicTacToe.com</li>
</ul>
</nav>
<div class="gameContainer">
<div class="container">
<div class="line"></div>
<div class="box bt-0 bl-0"><span class="boxtext"></span></div>
<div class="box bt-0"><span class="boxtext"></span></div>
<div class="box bt-0 br-0"><span class="boxtext"></span></div>
<div class="box bl-0"><span class="boxtext"></span></div>
<div class="box"><span class="boxtext"></span></div>
<div class="box br-0"><span class="boxtext"></span></div>
<div class="box bl-0 bb-0"><span class="boxtext"></span></div>
<div class="box bb-0"><span class="boxtext"></span></div>
<div class="box bb-0 br-0"><span class="boxtext"></span></div>
</div>
<div class="gameInfo">
<h1>Welcome to Tic Tac MyTicTacToe</h1>
<div>
<span class="info">Turn for X</span>
<button id="reset">Reset</button>
</div>
<div class="imgbox">
<img src="excited.gif" alt="" />
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Full CSS
@import url('https://fonts.googleapis.com/css2?family=Baloo+Bhaina+2&family=Roboto&display=swap');
*{
margin: 0;
padding: 0;
}
nav{
background-color: rgb(37, 9, 37);
color: white;
height: 65px;
font-size: 27px;
display: flex;
align-items: center;
padding: 0 12px;
font-family: 'Roboto', sans-serif;
}
nav ul{
list-style-type: none;
}
.gameContainer{
display: flex;
justify-content: center;
margin-top: 50px;
}
.container{
display: grid;
grid-template-rows: repeat(3, 10vw);
grid-template-columns: repeat(3, 10vw);
font-family: 'Roboto', sans-serif;
position: relative;
}
.box{
border: 2px solid black;
font-size: 8vw;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.box:hover{
background-color: rgb(242, 234, 250);
}
.info {
font-size: 22px;
}
.gameInfo{
padding: 0 34px;
font-family: 'Baloo Bhaina 2', cursive;
}
.gameInfo h1{
font-size: 2.5rem;
}
.imgbox img{
width: 0;
transition: width 1s ease-in-out;
}
.br-0{
border-right: 0;
}
.bl-0{
border-left: 0;
}
.bt-0{
border-top: 0;
}
.bb-0{
border-bottom: 0;
}
#reset {
margin: 0 23px;
padding: 1px 18px;
background: #f3e7f9;
border-radius: 6px;
cursor: pointer;
font-family: 'Baloo Bhaina 2';
font-size: 15px;
font-weight: bolder;
}
.line{
background-color: black;
height: 3px;
width: 0;
position: absolute;
background-color: #911d91;
transition: width 1s ease-in-out;
}
@media screen and (max-width: 950px)
{
.gameContainer{
flex-wrap: wrap;
}
.gameInfo{
margin-top: 34px;
}
.gameInfo h1{
font-size: 1.5rem;
}
.container {
grid-template-rows: repeat(3, 20vw);
grid-template-columns: repeat(3, 20vw);
}
}