1 min read

A Game You Can Create In 15 Minutes Using HTML CSS and Javascript

Last Update: 10 April, 2022

Create a game in only 15 minutes to with all the tools you probably already know. All the code necessary to get this game up and running is in the post but there is a lot of room for improvement. Challenge yourself by creating the game yourself and improving upon it.

§Project Description

We are going to be building a simple memory game where you can improve in many ways if you want to in the future. It's very easy to create and a good practice your Javascript skills. Basically you try to find the matching pics and win the game. Don't worry if you are just a beginner, the code should be easy enough for you to understand. HTML and CSS is very basic. In the javascript part I tried to explain the code in the comments.

I didn't implement any logic for actually winning the game, what happens when you win the game, keeping score or restarting the game. These are only some of the things you can implement in yours. Go check it out.

§The Basic HTML Setup

As I said before the HTML setup is very basic.

<!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"> <link rel="stylesheet" href="style.css"> <script defer src="main.js"></script> <title>Memory Game</title> </head> <body> <h1>Find the matching pics</h1> <div class="board-container"> {# Our board will appear here #} </div> </body> </html>

All the necessary CSS that I used:

/* /style.css */ body { background-color: azure; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; } .board-container { background-color: rgb(65, 78, 78); width: 600px; height: 600px; display: grid; grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(6, 1fr); grid-gap:10px; padding: 20px; border-radius: 20px; } .board-container > * { display: flex; justify-content: center; align-items: center; border-radius: 5px; }

§And Javascript To Make It All Happen

First of all, get all the images you want to use in your game. If you don't wanna bother looking for a bunch of images here are mine (I mean the ones I found online that were free).

// /main.js // The logic to randomize the image array const shuffle = (objects) => { for (let i = objects.length - 1; i > 0; i--) { let j = Math.floor(Math.random() * (i + 1)); let temp = objects[i]; objects[i] = objects[j]; objects[j] = temp; } } window.onload = async () => { // get the board container let boardContainer = await document.querySelector('.board-container'); // doubling my array size and randomizing the contents const doubleAndRender = async (objects, objectsLength) => { for (let i = 0; i < objectsLength; i++){ objects.push({"id":19+i, "src": `${i+1}.png`}) } // shuffling my array a bunch of times // not really necessary to do it 3 times though :) await shuffle(objects); await shuffle(objects); await shuffle(objects); for(let i = 0; i < objects.length; i++){ let div = document.createElement("div"); div.style.background = "red"; // give the png number as a class to be used later div.classList.add("grid-item", `${objects[i]["id"]}.png`) // id will get the number of the png without the ".png" extension div.setAttribute("id", `${objects[i]["id"]}`) boardContainer.appendChild(div) }; }; await shuffle(objects); await doubleAndRender(objects, 18); }

And this is where the magic happens. Logic can be found on in the comments below.

// keep track of how many images are open to be matched let num = 0; // first image clicked var target1; // second image clicked var target2; window.addEventListener('click', (e) => { // I numbered my pngs to be used thm easily here (1.png, 2.png, etc.) // and with pngNum I'm keeping track of the pngs let pngNum; // Checking for 3 different cases: // is it a grid-item // is it not active // does it have multiple classes if(e.target.classList.contains("grid-item") && e.target.classList[1] && !e.target.classList.contains("active")){ // grabbing the number of the png for matching later if(e.target.classList[1].split(".")[0] <= 18){ pngNum = e.target.classList[1].split(".")[0]; } else { pngNum = e.target.classList[1].split(".")[0] - 18; } // if there is no active open image if(num === 0){ target1 = e.target; // creating the image on on the grid item that's been clicked on let image = document.createElement("img"); image.src = `pngs/${pngNum}.png` image.style.maxWidth= '64px'; target1.appendChild(image) // Increment the number of active images to be matched num += 1; // when there's and active image already } else if(num == 1){ if(target1 !== e.target){ target2 = e.target; let image = document.createElement("img"); image.src = `pngs/${pngNum}.png` image.style.maxWidth= '64px'; target2.appendChild(image) num += 1; } // when two images are open/revealed } else if(num == 2){ // If both ids are higher than the number of pngs there can't be a match if(parseInt(target1.id) > 18 && (parseInt(target2.id) > 18)) { num = 0; target1.removeChild(target1.childNodes[0]); target2.removeChild(target2.childNodes[0]); } // If both ids are lower than the number of pngs there can't be a match else if (parseInt(target1.id) <= 18 && (parseInt(target2.id) <= 18)){ console.log("both low, not a match"); num = 0; target1.removeChild(target1.childNodes[0]); target2.removeChild(target2.childNodes[0]); } // Now ids are in range so start checking for a match else { if(parseInt(target1.id) > 18) { // Handle match if(parseInt(target1.id) - 18 == parseInt(target2.id)){ // Add active so they won't be mixed with the unmatched ones target1.classList.add("active") target2.classList.add("active") //Adding color as well as an indicator target1.style.background = "white"; target2.style.background = "white"; // the number of open images to be mathced should be 0 num = 0; }else { // No match target1.removeChild(target1.childNodes[0]); target2.removeChild(target2.childNodes[0]); num = 0 } }else if(parseInt(target2.id) > 18) { // Handle match if(parseInt(target2.id) - 18 == parseInt(target1.id)){ target1.classList.add("active") target2.classList.add("active") target1.style.background = "white"; target2.style.background = "white"; num = 0; } else { // No match target1.removeChild(target1.childNodes[0]); target2.removeChild(target2.childNodes[0]); num = 0; } } } } } })

§Next Steps and Possible Improvements

This project is not even close to being finished. Good thing about it is that it means there is room for improvement that you can do yourself to make it better. Maybe add a flip animation, implement a better logic for rendering the images into cards, make it so that people can create their own games with their own images... There are just so many things that can be added to this game.

As you can see this game was not hard to create at all. There are so many things you can create with basic HTML, CSS and javascript. This was just a quick example to what kind of things you can create by just using your basic web development knowledge.

Ilker Akbiyik