Building a Scalable Memory Game with Vanilla JavaScript

This week, I built a fully interactive Memory Game using only HTML, CSS, and Vanilla JavaScript — no libraries, no frameworks. Inspired by the classic card-matching game, the project features animated cards, themed levels, timed challenges, and a real-time scoring system.

🧠 A Card-Flipping Classic Reimagined for the Browser

In Week 7 of my Project52 journey — where I build 52 projects in 52 weeks to level up as a developer — I set out to build a modern, scalable Memory Game, using only the frontend trinity: HTML, CSS, and JavaScript.

The result?
An adaptive, multi-level memory challenge with themed symbols, animated transitions, scoreboards, and performance tracking — all powered by plain DOM manipulation and native JS logic.

🎮 The Concept

The core objective of the game is simple:

Flip two cards. If they match, they remain open. If not, they flip back. The game continues until all pairs are found.

But I wanted more than a basic 4x4 memory game. So I expanded it to include:

  • Multiple Themes: Animals 🐶, Symbols ♠, and Foods 🍎

  • Level Progression: From a 4×4 grid up to a 6×6 layout

  • Timed Previews: Cards are shown briefly before gameplay

  • Live Scoring System: Tracks correct/incorrect moves, points, time

  • Animated Transitions: Smooth flips, match pulses, and modals

  • Replayability: Score resets, level restarts, and a celebratory modal at completion

🧱 Architecture Overview

This is a purely frontend project, with no backend, no libraries, no frameworks. The project is fully self-contained and runs in any modern browser.

📦 Component Breakdown:

  • HTML: Semantic, accessible structure with logical layout

  • CSS: Grid-based layout, media queries for responsiveness, keyframe animations, transitions

  • JavaScript (Vanilla):

    • Game state management (cards, levels, score)

    • Timers and intervals

    • DOM manipulation and event delegation

    • Dynamic UI rendering and updates

    • Modal toggling and transitions

📚 Key Learnings (In Detail)

1. DOM Manipulation Mastery

Directly interacting with the DOM helped me deeply understand element creation, event binding, and how performance can be affected by excessive reflows or layout thrashing. I gained clarity on how modern frameworks abstract these mechanics.

2. State Management Without React

I had to build my own “mini store”:

let firstCard = null;
let secondCard = null;
let lockBoard = false;
let correctMoves = 0;
let incorrectMoves = 0;

This reinforced how game state must sync with UI state — something often abstracted in frameworks. Any desync could result in visual or logical bugs (e.g., cards flipping incorrectly or scoring being off).

3. CSS3 Animations + Game Logic

I used:

  • transform: rotateY(180deg) for flipping cards

  • @keyframes for a pulse effect on matches

  • Transitions to smooth interactions

But what I didn’t expect was timing conflicts — ensuring the game logic waits for animations to complete before evaluating a match was tricky. I had to set setTimeout delays in sync with animation durations.

4. Timing and Timer Management

I built:

  • A preview timer (countdown before real gameplay starts)

  • A gameplay timer (counting elapsed play time)

  • A points bonus system based on time

This involved using Date.now() for precise tracking and setInterval + clearInterval to manage transitions between game states.

5. Debugging Recursive Logic Bugs

A key bug I faced was infinite recursion.
In initGame() I called setTheme(), which itself called initGame() again if the game was already in progress.
The fix? I passed a flag skipInit = true to prevent reentry, which taught me the importance of guard clauses and execution context awareness.

🧩 Challenges Faced

  • UI and Logic Desync: Ensuring animations finished before logic executed

  • Mobile Responsiveness: Card sizes had to scale intelligently

  • User Feedback: Timing and visual cues had to be just right

  • Game Loop Integrity: Ensuring that matched pairs were correctly calculated and that state reset cleanly each level

🔧 Future Enhancements

  • Add localStorage support for saving scores

  • Introduce dark mode and sound FX

  • Allow users to create custom themes

  • Add leaderboards and time-based challenges

  • Eventually, convert this into a progressive web app (PWA)

🌐 Live Demo & Code

🎮 Play the Game: Access the Game

📌 Why This Project Matters

Most developers today start directly with frameworks. But mastering the fundamentals builds real confidence. This project helped me:

  • Understand the lifecycle of interactive components

  • Improve debugging skills by working directly with the browser console

  • Develop a deeper appreciation for game loops and state machines

Thanks for reading.
– Atul Verma
📍 Marketer turned developer| Building 52 Projects in 52 Weeks
🔁 #Project52 | 💻 #FrontendDev | 🎮 #GameDev