How to create a memory card game using html, css and JS
Memory Card Game is a classic puzzle game designed to test your focus and memory skills. In this game players mix pairs of cards by turning them over. This is a fascinating project for beginners to learn JavaScript by implementing features like event handling, timers, and game logic.
Features of the Memory Card Game
- Dynamic Card Flip Animation: Cards flip with smooth animations using CSS transitions and JavaScript classes.
- Timer and Flip Counter: Keep track of time and number of flips to increase competitiveness.
- Shuffle Cards: Randomize the card positions after each game for endless fun.
- Responsive Design: The game adapts to different screen sizes using media queries.
How to Create a Memory Card Game in JavaScript
Create Html :
Define a grid of cards, each with a front and back view:
Memory Card Game
-
-
-
-
-
-
-
-
-
-
-
-
Time: 20s
Flips: 0
CSS for Styling :
Use flexbox for grid alignment and CSS animations for the flipping effect.
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
p{
font-size: 20px;
}
body{
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #6563ff;
}
::selection{
color: #fff;
background: #6563ff;
}
.wrapper{
padding: 25px;
background: #f8f8f8;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.cards, .card, .view, .details, p{
display: flex;
align-items: center;
justify-content: center;
}
.cards{
height: 350px;
width: 350px;
flex-wrap: wrap;
justify-content: space-between;
}
.cards .card{
cursor: pointer;
position: relative;
perspective: 1000px;
transform-style: preserve-3d;
height: calc(100% / 4 - 10px);
width: calc(100% / 4 - 10px);
}
.card.shake{
animation: shake 0.35s ease-in-out;
}
@keyframes shake {
0%, 100%{
transform: translateX(0);
}
20%{
transform: translateX(-13px);
}
40%{
transform: translateX(13px);
}
60%{
transform: translateX(-8px);
}
80%{
transform: translateX(8px);
}
}
.cards .card .view{
width: 100%;
height: 100%;
user-select: none;
pointer-events: none;
position: absolute;
background: #fff;
border-radius: 7px;
backface-visibility: hidden;
transition: transform 0.25s linear;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}
.card .front-view img{
max-width: 17px;
}
.card .back-view{
transform: rotateY(-180deg);
}
.card .back-view img{
max-width: 40px;
}
.card.flip .front-view{
transform: rotateY(180deg);
}
.card.flip .back-view{
transform: rotateY(0);
}
.details{
width: 100%;
margin-top: 15px;
padding: 0 20px;
border-radius: 7px;
background: #fff;
height: calc(100% / 4 - 30px);
justify-content: space-between;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
}
.details p{
font-size: 18px;
height: 17px;
padding-right: 18px;
border-right: 1px solid #ccc;
}
.details p span{
margin-left: 8px;
}
.details p b{
font-weight: 500;
}
.details button{
cursor: pointer;
font-size: 14px;
color: #6563ff;
border-radius: 4px;
padding: 4px 11px;
background: #fff;
border: 2px solid #6563ff;
transition: 0.3s ease;
}
.details button:hover{
color: #fff;
background: #6563ff;
}
@media screen and (max-width: 700px) {
.cards{
height: 350px;
width: 350px;
}
.card .front-view img{
max-width: 16px;
}
.card .back-view img{
max-width: 40px;
}
}
@media screen and (max-width: 530px) {
.cards{
height: 300px;
width: 300px;
}
.card .back-view img{
max-width: 35px;
}
.details{
margin-top: 10px;
padding: 0 15px;
height: calc(100% / 4 - 20px);
}
.details p{
height: 15px;
font-size: 17px;
padding-right: 13px;
}
.details button{
font-size: 13px;
padding: 5px 10px;
border: none;
color: #fff;
background: #6563ff;
}
}
JavaScript for Game Logic : Implement functionality to shuffle cards, handle card flips, and detect matches:
const cards = document.querySelectorAll(".card"),
timeTag = document.querySelector(".time b"),
flipsTag = document.querySelector(".flips b"),
refreshBtn = document.querySelector(".details button");
let maxTime = 20;
let timeLeft = maxTime;
let flips = 0;
let matchedCard = 0;
let disableDeck = false;
let isPlaying = false;
let cardOne, cardTwo, timer;
function initTimer() {
if(timeLeft <= 0) {
return clearInterval(timer);
}
timeLeft--;
timeTag.innerText = timeLeft;
}
function flipCard({target: clickedCard}) {
if(!isPlaying) {
isPlaying = true;
timer = setInterval(initTimer, 1000);
}
if(clickedCard !== cardOne && !disableDeck && timeLeft > 0) {
flips++;
flipsTag.innerText = flips;
clickedCard.classList.add("flip");
if(!cardOne) {
return cardOne = clickedCard;
}
cardTwo = clickedCard;
disableDeck = true;
let cardOneImg = cardOne.querySelector(".back-view img").src,
cardTwoImg = cardTwo.querySelector(".back-view img").src;
matchCards(cardOneImg, cardTwoImg);
}
}
function matchCards(img1, img2) {
if(img1 === img2) {
matchedCard++;
if(matchedCard == 6 && timeLeft > 0) {
return clearInterval(timer);
}
cardOne.removeEventListener("click", flipCard);
cardTwo.removeEventListener("click", flipCard);
cardOne = cardTwo = "";
return disableDeck = false;
}
setTimeout(() => {
cardOne.classList.add("shake");
cardTwo.classList.add("shake");
}, 400);
setTimeout(() => {
cardOne.classList.remove("shake", "flip");
cardTwo.classList.remove("shake", "flip");
cardOne = cardTwo = "";
disableDeck = false;
}, 1200);
}
function shuffleCard() {
timeLeft = maxTime;
flips = matchedCard = 0;
cardOne = cardTwo = "";
clearInterval(timer);
timeTag.innerText = timeLeft;
flipsTag.innerText = flips;
disableDeck = isPlaying = false;
let arr = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6];
arr.sort(() => Math.random() > 0.5 ? 1 : -1);
cards.forEach((card, index) => {
card.classList.remove("flip");
let imgTag = card.querySelector(".back-view img");
setTimeout(() => {
imgTag.src = `images/${arr[index]}.png`;
}, 500);
card.addEventListener("click", flipCard);
});
}
shuffleCard();
refreshBtn.addEventListener("click", shuffleCard);
cards.forEach(card => {
card.addEventListener("click", flipCard);
});
Interactive Features
- Add a Restart Button: Reset the game and shuffle cards.
- Introduce Levels: Increase the complexity with more cards.
- Display a Leaderboard: Track top scores based on flips and time.
Conclusion
Creating a memory card game is a great way to practice JavaScript programming and understand core concepts like DOM manipulation, event handling, and animation. With additional features and reactivity, this project could be an important step forward for the creation of advanced interactive games.
JavaScript Card Game Source Code
Send download link to: