• Home
  • /
  • Typing Speed Test with Timer & WPM Tracker using HTML CSS JS

Typing Speed Test with Timer & WPM Tracker using HTML CSS JS

HTML

				
					<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Typing Speed Test | Learn With Arshyan</title>
 <style>
  * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  background: #f0f4ff;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 20px;
}

.typing-container {
  background: #fff;
  padding: 30px 40px;
  border-radius: 10px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
  text-align: center;
  width: 100%;
  max-width: 650px;
}

h1 {
  color: #6200ea;
  margin-bottom: 10px;
}

label, select {
  font-size: 16px;
  margin: 10px 0;
}

select {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid #ccc;
  margin-left: 10px;
}

#quote-display {
  font-size: 18px;
  margin: 20px 0;
  color: #333;
  min-height: 60px;
}

#quote-input {
  width: 100%;
  height: 100px;
  font-size: 16px;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 6px;
  margin-bottom: 20px;
  resize: none;
}

.info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 15px;
  font-size: 16px;
  color: #333;
}

.buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-bottom: 20px;
}

.buttons button {
  padding: 10px 16px;
  background: #6200ea;
  color: #fff;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: bold;
  transition: background 0.3s ease;
}

.buttons button:hover {
  background: #4a00c8;
}

.results {
  background: #e8f0ff;
  padding: 20px;
  border-radius: 10px;
  text-align: left;
  display: none;
}

.results h2 {
  color: #003366;
  margin-bottom: 10px;
}

.results p {
  font-size: 16px;
  margin: 4px 0;
}

@media (max-width: 600px) {
  .info {
    flex-direction: column;
    gap: 10px;
    align-items: center;
  }

  #quote-input {
    height: 80px;
  }
}

 </style>
</head>
<body>

  <div class="typing-container">
    <h1>Typing Speed Test</h1>

    <label for="duration">Select Time:</label>
    <select id="duration">
      <option value="30">30 seconds</option>
      <option value="60" selected>60 seconds</option>
      <option value="120">120 seconds</option>
    </select>

    <div class='code-block code-block-2' style='margin: 8px 0; clear: both;'>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2094722033678002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2094722033678002"
     data-ad-slot="2248279416"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>
<p id="quote-display"></p>
    <textarea id="quote-input" placeholder="Start typing here..." disabled></textarea>

    <div class="info">
      <span id="timer">Time: 60s</span>
      <span id="wpm">WPM: 0</span>
    </div>

    <div class="buttons">
      <button onclick="startTest()">Start</button>
      <button onclick="pauseTest()">Pause</button>
      <button onclick="resumeTest()">Resume</button>
      <button onclick="stopTest()">Stop</button>
    </div>

    <div id="results" class="results"></div>
  </div>

  <script>
    const quotes = [
  "Programming is not about typing, it’s about thinking.",
  "Typing fast is useless if you can’t think fast.",
  "Every great developer you know got there by solving problems.",
  "Experience is the name everyone gives to their mistakes.",
  "Make it work, make it right, make it fast."
];

let timerInterval;
let remainingTime = 60;
let totalTime = 60;
let isPaused = false;

const quoteDisplay = document.getElementById("quote-display");
const quoteInput = document.getElementById("quote-input");
const timer = document.getElementById("timer");
const wpmDisplay = document.getElementById("wpm");
const durationSelect = document.getElementById("duration");
const resultsBox = document.getElementById("results");

function getRandomQuote() {
  return quotes[Math.floor(Math.random() * quotes.length)];
}

function renderNewQuote() {
  const quote = getRandomQuote();
  quoteDisplay.textContent = quote;
  quoteInput.value = "";
  quoteInput.disabled = false;
  quoteInput.focus();
  resultsBox.style.display = "none";
}

function updateTimer() {
  if (!isPaused) {
    remainingTime--;
    timer.textContent = `Time: ${remainingTime}s`;

    const typedWords = quoteInput.value.trim().split(/\s+/).length;
    const minutesElapsed = (totalTime - remainingTime) / 60;
    const wpm = Math.round(typedWords / minutesElapsed || 0);
    wpmDisplay.textContent = `WPM: ${wpm}`;

    if (remainingTime <= 0) {
      stopTest(true);
    }
  }
}

function startTest() {
  totalTime = parseInt(durationSelect.value);
  remainingTime = totalTime;
  isPaused = false;

  timer.textContent = `Time: ${totalTime}s`;
  wpmDisplay.textContent = `WPM: 0`;
  renderNewQuote();

  clearInterval(timerInterval);
  timerInterval = setInterval(updateTimer, 1000);
}

function pauseTest() {
  isPaused = true;
}

function resumeTest() {
  isPaused = false;
}

function stopTest(auto = false) {
  clearInterval(timerInterval);
  quoteInput.disabled = true;

  const typedText = quoteInput.value.trim();
  const wordCount = typedText.length > 0 ? typedText.split(/\s+/).length : 0;
  const charCount = typedText.length;
  const minutes = totalTime / 60;
  const wpm = Math.round(wordCount / minutes || 0);

  resultsBox.innerHTML = `
    <h2>Results Summary</h2>
    <p><strong>Time:</strong> ${totalTime} seconds</p>
    <p><strong>Words Typed:</strong> ${wordCount}</p>
    <p><strong>Characters Typed:</strong> ${charCount}</p>
    <p><strong>Words Per Minute (WPM):</strong> ${wpm}</p>
  `;
  resultsBox.style.display = "block";

  if (!auto) {
    alert("Test stopped.");
  }
}

  </script>
</body>
</html>

				
			

Share this post

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top