Typing Speed Test (WPM & Accuracy)

Real-time typing test application measuring Words Per Minute (WPM), CPM, character accuracy percentage, and countdown timers.

Difficulty: Beginner Est. Time: 25 mins Vanilla JS (ES6+) Includes HTML, CSS, JS & README (.ZIP)
Live UI Runner

Typing Speed Test (WPM & Accuracy)

live-sandbox://typing-speed-test

1. Project Overview & Features

The Typing Speed Test (WPM & Accuracy) is an essential frontend project designed to help you bridge the gap between learning JavaScript syntax and building interactive, responsive web applications.

Key Features Implemented:

  • Dynamic text display with green (correct) and red (mistake) highlighting
  • Calculates live WPM, CPM, and Accuracy %
  • 60-second test countdown with restart

2. Step-by-Step Code Walkthrough

A Step 1: Semantic HTML Structure

We structure the interface using clean, semantic HTML elements. This ensures maximum accessibility and provides intuitive hooks for CSS classes and JavaScript query selectors.

HTML (index.html)
<div class="typing-card">
  <div class="typing-header">
    <div class="stat"><span class="val" id="wpm-val">0</span><span class="lbl">WPM</span></div>
    <div class="stat"><span class="val" id="acc-val">100%</span><span class="lbl">Accuracy</span></div>
    <div class="stat"><span class="val" id="time-val">60s</span><span class="lbl">Time Left</span></div>
  </div>

  <div class="text-display" id="text-display"></div>
  <textarea id="typing-input" placeholder="Start typing here to begin test..."></textarea>
  <button id="restart-typing-btn" class="btn-restart-type"><i class="fas fa-redo"></i> Restart Test</button>
</div>

B Step 2: Styling & Responsive CSS

Modern CSS flexbox and grid layouts are used to make the UI look polished, centered, and responsive across desktop, tablet, and mobile screens.

CSS (style.css)
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
body {
  background: #0f172a;
  color: #f8fafc;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.typing-card {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 24px;
  padding: 28px;
  width: 100%;
  max-width: 520px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
}
.typing-header {
  display: flex;
  justify-content: space-around;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 14px;
  padding: 12px;
  margin-bottom: 20px;
}
.stat { text-align: center; }
.stat .val { font-size: 1.5rem; font-weight: 800; color: #f97316; display: block; }
.stat .lbl { font-size: 0.75rem; color: #94a3b8; font-weight: 600; }
.text-display {
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 16px;
  font-size: 1.1rem;
  line-height: 1.6;
  margin-bottom: 14px;
  user-select: none;
  min-height: 100px;
}
.text-display span.correct { color: #10b981; }
.text-display span.incorrect { color: #ef4444; background: rgba(239, 68, 68, 0.2); border-radius: 2px; }
.text-display span.current { text-decoration: underline; color: #38bdf8; }
#typing-input {
  width: 100%;
  height: 90px;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 12px;
  color: #f8fafc;
  padding: 12px;
  font-size: 1rem;
  outline: none;
  resize: none;
  margin-bottom: 14px;
}
#typing-input:focus { border-color: #f97316; }
.btn-restart-type {
  width: 100%;
  background: #f97316;
  color: #ffffff;
  border: none;
  padding: 12px;
  border-radius: 10px;
  font-weight: 700;
  cursor: pointer;
}

C Step 3: JavaScript Logic & Event Handling

Here is the complete JavaScript code handling the state, event listeners, mathematical logic, and dynamic DOM rendering:

JavaScript (script.js)
const sampleParagraphs = [
  "JavaScript is the programming language of the Web. Easy to learn and powerful.",
  "Practice typing every day to improve your speed, accuracy, and coding confidence.",
  "Building beginner projects is the most effective way to master frontend development."
];

let targetText = sampleParagraphs[0];
let timeLeft = 60;
let timer = null;
let isStarted = false;
let mistakes = 0;

const textDisplay = document.getElementById('text-display');
const typingInput = document.getElementById('typing-input');
const wpmVal = document.getElementById('wpm-val');
const accVal = document.getElementById('acc-val');
const timeVal = document.getElementById('time-val');
const restartBtn = document.getElementById('restart-typing-btn');

function renderText() {
  textDisplay.innerHTML = '';
  targetText.split('').forEach((char, i) => {
    const span = document.createElement('span');
    span.innerText = char;
    if (i === 0) span.classList.add('current');
    textDisplay.appendChild(span);
  });
}

function processTyping() {
  const enteredText = typingInput.value;
  const spans = textDisplay.querySelectorAll('span');

  if (!isStarted && enteredText.length > 0) {
    isStarted = true;
    timer = setInterval(() => {
      timeLeft--;
      timeVal.textContent = `${timeLeft}s`;
      if (timeLeft <= 0) {
        clearInterval(timer);
        typingInput.disabled = true;
      }
    }, 1000);
  }

  mistakes = 0;
  spans.forEach((span, i) => {
    const char = enteredText[i];
    span.className = '';
    if (char == null) {
      if (i === enteredText.length) span.classList.add('current');
    } else if (char === span.innerText) {
      span.classList.add('correct');
    } else {
      span.classList.add('incorrect');
      mistakes++;
    }
  });

  // Calculate WPM and Accuracy
  const timeElapsed = 60 - timeLeft || 1;
  const wpm = Math.round(((enteredText.length / 5) / (timeElapsed / 60))) || 0;
  const accuracy = Math.max(0, Math.round(((enteredText.length - mistakes) / (enteredText.length || 1)) * 100));

  wpmVal.textContent = wpm;
  accVal.textContent = `${accuracy}%`;
}

function restartTest() {
  clearInterval(timer);
  timeLeft = 60;
  isStarted = false;
  typingInput.disabled = false;
  typingInput.value = '';
  timeVal.textContent = '60s';
  wpmVal.textContent = '0';
  accVal.textContent = '100%';
  targetText = sampleParagraphs[Math.floor(Math.random() * sampleParagraphs.length)];
  renderText();
}

typingInput.addEventListener('input', processTyping);
restartBtn.addEventListener('click', restartTest);

renderText();

3. Core JavaScript Concepts You Learned

Key Event Handling

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

Character-by-Character Validation

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

WPM & Accuracy Calculations

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

Interval Timers

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

4. How to Run Locally on Your Computer

  1. Download the project ZIP: Click the Download Project (.ZIP) button at the top or in the live runner to save typing-speed-test-project.zip.
  2. Extract the archive: Unzip the downloaded file. Inside you will find separate index.html, style.css, script.js, index-standalone.html, and a comprehensive README.md.
  3. Open in any browser: Simply double-click index.html (or index-standalone.html) to open and test immediately in Chrome, Firefox, Safari, or Edge.
  4. Edit in Visual Studio Code: Open the extracted folder in VS Code. Right-click index.html and select "Open with Live Server" to enjoy instant live reloading as you modify HTML, CSS, or JS!

Bonus Challenges for Learners

Ready to level up? Try adding these extra features on your own:

  • Add sound effects or audio feedback for user button clicks.
  • Add custom theme color customizer with CSS variables.
  • Export the results to PDF or copy as a formatted text summary.

Other Beginner Projects You Might Like

Beginner30 mins
Math & Calculators

Interactive Calculator

Build a sleek, fully functional calculator with arithmetic operations, decimal support, backspace, and calculation history.

DOM ManipulationEvent Listenerseval & Math Logic+2
Beginner25 mins
Productivity & UI

Smart To-Do List with LocalStorage

A full-featured task manager with local storage persistence, filtering (All, Active, Completed), task counter, and priority levels.

Safe LocalStorage APIArray Methods (map, filter, unshift)Event Delegation & Keyboard Triggers+2
Beginner20 mins
Timers & Clocks

Digital & Analog Dual Clock

A dynamic dual-mode clock with synchronized analog ticking hands, 12h/24h digital time, date formatting, and light/dark theme switch.

setInterval & requestAnimationFrameDate Object MethodsCSS transform: rotate()+2