JSFiddle - React, Tailwind, and code Playground
by Vijay Pancholi
HTML
<div class="container">
<h1>Typing Speed Test</h1>
<p id="quote">Loading...</p>
<textarea id="input" placeholder="Start typing here..."></textarea>
<div class="stats">
<p><strong>WPM:</strong> <span id="wpm">0</span></p>
<p><strong>Accuracy:</strong> <span id="accuracy">100%</span></p>
<button onclick="resetTest()">Restart</button>
</div>
</div>
CSS
body {
font-family: Arial, sans-serif;
background: #f0f0f0;
text-align: center;
padding: 50px;
}
.container {
max-width: 600px;
margin: auto;
background: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
#quote {
font-size: 20px;
margin-bottom: 20px;
}
textarea {
width: 100%;
height: 100px;
font-size: 18px;
padding: 10px;
}
.stats {
margin-top: 20px;
}
button {
margin-top: 10px;
padding: 8px 20px;
font-size: 16px;
}
JavaScript
const sentences = [
"JavaScript is fun to learn.",
"Practice makes you better.",
"The quick brown fox jumps over the lazy dog.",
"Typing games improve your speed and accuracy.",
];
let quote = document.getElementById('quote');
let input = document.getElementById('input');
let wpmDisplay = document.getElementById('wpm');
let accuracyDisplay = document.getElementById('accuracy');
let currentSentence = "";
let startTime = null;
let timerStarted = false;
function loadSentence() {
currentSentence = sentences[Math.floor(Math.random() * sentences.length)];
quote.innerText = currentSentence;
input.value = "";
wpmDisplay.textContent = 0;
accuracyDisplay.textContent = "100%";
startTime = null;
timerStarted = false;
}
function calculateWPM(text, timeElapsedInSeconds) {
const words = text.trim().split(/\s+/).length;
return Math.round((words / timeElapsedInSeconds) * 60);
}
function calculateAccuracy(original, typed) {
let correct = 0;
for (let i = 0; i < typed.length; i++) {
if (typed[i] === original[i]) correct++;
}
return Math.round((correct / original.length) * 100);
}
input.addEventListener('input', () => {
if (!timerStarted) {
startTime = new Date();
timerStarted = true;
}
const typedText = input.value;
const elapsedTime = (new Date() - startTime) / 1000;
const wpm = calculateWPM(typedText, elapsedTime);
const accuracy = calculateAccuracy(currentSentence, typedText);
wpmDisplay.textContent = wpm;
accuracyDisplay.textContent = accuracy + "%";
if (typedText === currentSentence) {
input.disabled = true;
}
});
function resetTest() {
input.disabled = false;
loadSentence();
}
window.onload = loadSentence;