
Typing test
Prompt
Please create a javascript-based typing test - it should show random words in sequence and measure typing speed to get through 100 words, and take keyboard input
A system prompt was added to support web rendering
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Simple Typing Test (100 Words)</title> <style> body{ font-family: Arial, Helvetica, sans-serif; margin:40px; line-height:1.5em; background:#f5f7fa; } h1{margin-bottom:10px} #wordContainer{ background:#fff; padding:20px; border:1px solid #ccc; border-radius:6px; min-height:120px; font-size:22px; user-select:none; } #wordContainer span{ margin-right:6px; } #wordContainer .current{ text-decoration:underline; color:#1a73e8; } #wordContainer .correct{ color:#28a745; } #wordContainer .incorrect{ color:#dc3545; } #typeInput{ width:100%; padding:12px; font-size:20px; margin-top:25px; border:2px solid #1a73e8; border-radius:4px; box-sizing:border-box; } #stats{ margin-top:25px; font-size:20px; } #startBtn,#resetBtn{ margin-top:20px; padding:10px 18px; background:#1a73e8; color:#fff; font-size:16px; border:none; border-radius:4px; cursor:pointer; } #resetBtn{ display:none; background:#6c757d; } </style> </head> <body> <h1>Typing Test – 100 Random Words</h1> <div id="wordContainer"></div> <input id="typeInput" placeholder="Start typing here…" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" disabled> <div id="stats"></div> <button id="startBtn">Start Test</button> <button id="resetBtn">Restart</button> <script> (function(){ // ================================================ // Configuration / Data // ================================================ const WORD_COUNT = 100; const WORD_BANK = [ "the","of","and","to","a","in","is","you","that","it","he","was","for","on","are", "as","with","his","they","I","at","be","this","have","from","or","one","had","by", "word","but","not","what","all","were","we","when","your","can","said","there","use", "an","each","which","she","do","how","their","if","will","up","other","about","out", "many","then","them","these","so","some","her","would","make","like","him","into", "time","has","look","two","more","write","go","see","number","no","way","could", "people","my","than","first","water","been","call","who","oil","its","now","find", "long","down","day","did","get","come","made","may","part","new","sound" ]; // ================================================ // DOM references // ================================================ const wordContainer = document.getElementById('wordContainer'); const input = document.getElementById('typeInput'); const statsDiv = document.getElementById('stats'); const startBtn = document.getElementById('startBtn'); const resetBtn = document.getElementById('resetBtn'); // ================================================ // State // ================================================ let words = []; let currentIndex = 0; let started = false; let startTime = 0; let correctWords = 0; let totalTypedWords = 0; // ================================================ // Functions // ================================================ function randomWord(){ return WORD_BANK[Math.floor(Math.random()*WORD_BANK.length)]; } function generateWords(){ words = []; for(let i=0;i<WORD_COUNT;i++){ words.push(randomWord()); } } function renderWords(){ wordContainer.innerHTML = words.map((w,i)=>`<span id="w${i}" class="${i===0?'current':''}">${w}</span>`).join(' '); } function resetTest(){ currentIndex = 0; started = false; startTime = 0; correctWords = 0; totalTypedWords = 0; statsDiv.textContent = ''; input.value = ''; input.disabled = true; startBtn.style.display = ''; resetBtn.style.display = 'none'; generateWords(); renderWords(); } function startTest(){ input.disabled = false; input.focus(); startBtn.style.display = 'none'; resetBtn.style.display = ''; } function finishTest(){ const elapsedSec = (Date.now() - startTime) / 1000; const wpm = (correctWords / elapsedSec) * 60; const accuracy = (correctWords / totalTypedWords) * 100 || 0; statsDiv.innerHTML = ` <strong>Completed!</strong><br> Time: ${elapsedSec.toFixed(1)} s<br> Correct Words: ${correctWords}/${WORD_COUNT}<br> Accuracy: ${accuracy.toFixed(1)}%<br> WPM: ${wpm.toFixed(1)} `; input.disabled = true; input.value = ''; } function handleInput(e){ // Start timer on first key press if(!started){ started = true; startTime = Date.now(); } // Detect space or enter if(e.key === ' ' || e.key === 'Enter'){ e.preventDefault(); // prevent adding space to input const typed = input.value.trim(); const currentWord = words[currentIndex]; const span = document.getElementById(`w${currentIndex}`); if(typed.length>0){ // ignore consecutive spaces if(typed === currentWord){ span.classList.add('correct'); correctWords++; }else{ span.classList.add('incorrect'); } span.classList.remove('current'); currentIndex++; totalTypedWords++; if(currentIndex < WORD_COUNT){ document.getElementById(`w${currentIndex}`).classList.add('current'); } input.value = ''; if(currentIndex === WORD_COUNT){ finishTest(); } } } } // ================================================ // Event Listeners // ================================================ input.addEventListener('keydown', handleInput); startBtn.addEventListener('click', startTest); resetBtn.addEventListener('click', resetTest); // ================================================ // Init // ================================================ resetTest(); // generate first set })(); </script> </body> </html> ```
Drag to resize
Here is a self-contained, JavaScript-based typing test. Copy the code below into an HTML file and open it in your browser to begin. ```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</title> <style> :root { --background-color: #2c3e50; --text-color: #ecf0f1; --main-color: #3498db; --incorrect-color: #e74c3c; --correct-color: #2ecc71; --sub-color: #95a5a6; --input-bg-color: #34495e; } body { background-color: var(--background-color); color: var(--text-color); font-family: 'Roboto Mono', monospace; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 20px; box-sizing: border-box; } .test-container { width: 100%; max-width: 800px; text-align: center; } h1 { color: var(--main-color); font-size: 2.5rem; margin-bottom: 1rem; } p.instructions { color: var(--sub-color); font-size: 1rem; margin-bottom: 2rem; } #stats { display: flex; justify-content: center; align-items: center; gap: 2rem; font-size: 1.5rem; margin-bottom: 1.5rem; color: var(--main-color); } #words-container { background-color: var(--input-bg-color); padding: 1.5rem; border-radius: 8px; font-size: 1.5rem; margin-bottom: 1.5rem; height: 140px; overflow: hidden; text-align: left; line-height: 2.2; position: relative; } .word { margin: 0 5px; padding: 2px 4px; border-radius: 4px; transition: color 0.15s, background-color 0.15s; } .word.current { background-color: var(--main-color); color: var(--background-color); } .word.correct { color: var(--correct-color); } .word.incorrect { color: var(--incorrect-color); text-decoration: underline; } #typing-input { width: 90%; padding: 1rem; font-size: 1.5rem; border-radius: 8px; border: 2px solid var(--main-color); background-color: var(--input-bg-color); color: var(--text-color); font-family: inherit; text-align: center; } #typing-input:focus { outline: none; border-color: var(--correct-color); box-shadow: 0 0 10px var(--correct-color); } #restart-btn { margin-top: 1.5rem; padding: 1rem 2rem; font-size: 1.2rem; border-radius: 8px; border: none; background-color: var(--main-color); color: var(--text-color); cursor: pointer; transition: background-color 0.2s; } #restart-btn:hover { background-color: #2980b9; } #results { margin-top: 2rem; font-size: 1.2rem; background-color: var(--input-bg-color); padding: 2rem; border-radius: 8px; } #results h2 { color: var(--main-color); margin-top: 0; font-size: 2rem; } .result-item { display: flex; justify-content: space-between; max-width: 300px; margin: 1rem auto; font-size: 1.2rem; } .result-item span:first-child { color: var(--sub-color); } .result-item span:last-child { color: var(--text-color); font-weight: bold; } .hidden { display: none; } </style> </head> <body> <div class="test-container"> <h1>Typing Test</h1> <p class="instructions">Type the words below. The test will begin on your first keystroke.</p> <div id="game-area"> <div id="stats"> <div id="timer">Time: 0:00</div> </div> <div id="words-container"></div> <input type="text" id="typing-input" autofocus autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /> </div> <div id="results" class="hidden"> <h2>Results</h2> <div class="result-item"> <span>Words Per Minute (WPM)</span> <span id="wpm">0</span> </div> <div class="result-item"> <span>Accuracy</span> <span id="accuracy">0%</span> </div> <div class="result-item"> <span>Correct Words</span> <span id="correct-words">0</span> </div> <div class="result-item"> <span>Incorrect Words</span> <span id="incorrect-words">0</span> </div> </div> <button id="restart-btn">Restart Test</button> </div> <script> document.addEventListener('DOMContentLoaded', () => { const wordList = [ 'the', 'be', 'to', 'of', 'and', 'a', 'in', 'that', 'have', 'I', 'it', 'for', 'not', 'on', 'with', 'he', 'as', 'you', 'do', 'at', 'this', 'but', 'his', 'by', 'from', 'they', 'we', 'say', 'her', 'she', 'or', 'an', 'will', 'my', 'one', 'all', 'would', 'there', 'their', 'what', 'so', 'up', 'out', 'if', 'about', 'who', 'get', 'which', 'go', 'me', 'when', 'make', 'can', 'like', 'time', 'no', 'just', 'him', 'know', 'take', 'people', 'into', 'year', 'your', 'good', 'some', 'could', 'them', 'see', 'other', 'than', 'then', 'now', 'look', 'only', 'come', 'its', 'over', 'think', 'also', 'back', 'after', 'use', 'two', 'how', 'our', 'work', 'first', 'well', 'way', 'even', 'new', 'want', 'because', 'any', 'these', 'give', 'day', 'most', 'us', 'is', 'are', 'was', 'were', 'has', 'had', 'said', 'went', 'did', 'got', 'were', 'find', 'long', 'down', 'day', 'did', 'get', 'come', 'made', 'may', 'part', 'number', 'sound', 'no', 'most', 'people', 'my', 'over', 'know', 'water', 'than', 'call', 'first', 'who', 'may', 'down', 'side', 'been', 'now', 'find', 'head', 'stand', 'own', 'page', 'should', 'country', 'found', 'answer', 'school', 'grow', 'study', 'still', 'learn', 'plant', 'cover', 'food', 'sun', 'four', 'between', 'state', 'keep', 'eye', 'never', 'last', 'let', 'thought', 'city', 'tree', 'cross', 'farm', 'hard', 'start', 'might', 'story', 'saw', 'far', 'sea', 'draw', 'left', 'late', 'run', 'don\'t', 'while', 'press', 'close', 'night', 'real', 'life', 'few', 'north' ]; const WORDS_TO_TEST = 100; const gameAreaEl = document.getElementById('game-area'); const wordsContainerEl = document.getElementById('words-container'); const typingInputEl = document.getElementById('typing-input'); const timerEl = document.getElementById('timer'); const restartBtn = document.getElementById('restart-btn'); const resultsEl = document.getElementById('results'); const wpmEl = document.getElementById('wpm'); const accuracyEl = document.getElementById('accuracy'); const correctWordsEl = document.getElementById('correct-words'); const incorrectWordsEl = document.getElementById('incorrect-words'); let words = []; let currentWordIndex = 0; let correctCount = 0; let incorrectCount = 0; let timerInterval; let startTime; let gameActive = false; function initializeTest() { // Reset state currentWordIndex = 0; correctCount = 0; incorrectCount = 0; gameActive = false; clearInterval(timerInterval); // Show game, hide results gameAreaEl.classList.remove('hidden'); resultsEl.classList.add('hidden'); // Reset UI timerEl.textContent = "Time: 0:00"; typingInputEl.value = ''; typingInputEl.disabled = false; wordsContainerEl.innerHTML = ''; // Generate and display words words = generateWords(WORDS_TO_TEST); words.forEach((word, index) => { const wordSpan = document.createElement('span'); wordSpan.textContent = word; wordSpan.classList.add('word'); wordSpan.id = `word-${index}`; wordsContainerEl.appendChild(wordSpan); }); updateWordHighlight(); typingInputEl.focus(); } function generateWords(count) { const shuffled = wordList.sort(() => 0.5 - Math.random()); return shuffled.slice(0, count); } function updateWordHighlight() { // Remove previous highlight const currentWordEl = document.querySelector('.word.current'); if (currentWordEl) currentWordEl.classList.remove('current'); // Add new highlight const nextWordEl = document.getElementById(`word-${currentWordIndex}`); if (nextWordEl) { nextWordEl.classList.add('current'); // Scroll the word into view nextWordEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } function startGame() { if (gameActive) return; gameActive = true; startTime = new Date().getTime(); timerInterval = setInterval(updateTimer, 1000); } function updateTimer() { const currentTime = new Date().getTime(); const elapsedTime = Math.floor((currentTime - startTime) / 1000); const minutes = Math.floor(elapsedTime / 60); const seconds = elapsedTime % 60; timerEl.textContent = `Time: ${minutes}:${seconds.toString().padStart(2, '0')}`; } function checkWord() { const typedValue = typingInputEl.value.trim(); if (typedValue === '') return; const currentWord = words[currentWordIndex]; const currentWordEl = document.getElementById(`word-${currentWordIndex}`); if (typedValue === currentWord) { currentWordEl.classList.add('correct'); correctCount++; } else { currentWordEl.classList.add('incorrect'); incorrectCount++; } currentWordIndex++; if (currentWordIndex >= words.length) { endGame(); return; } updateWordHighlight(); typingInputEl.value = ''; } function endGame() { gameActive = false; clearInterval(timerInterval); typingInputEl.disabled = true; const endTime = new Date().getTime(); const elapsedTimeInMinutes = (endTime - startTime) / 1000 / 60; const calculatedWpm = Math.round(correctCount / elapsedTimeInMinutes) || 0; const calculatedAccuracy = Math.round((correctCount / (correctCount + incorrectCount)) * 100) || 0; wpmEl.textContent = calculatedWpm; accuracyEl.textContent = `${calculatedAccuracy}%`; correctWordsEl.textContent = correctCount; incorrectWordsEl.textContent = incorrectCount; gameAreaEl.classList.add('hidden'); resultsEl.classList.remove('hidden'); } typingInputEl.addEventListener('keydown', (e) => { if (!gameActive && e.key !== ' ' && e.key !== 'Enter' && e.key !== 'Tab') { startGame(); } if (e.key === ' ') { e.preventDefault(); // Prevent space from being typed checkWord(); } }); // For mobile or autocorrect scenarios where space might not be a keydown event typingInputEl.addEventListener('input', () => { if (typingInputEl.value.endsWith(' ')) { checkWord(); } }); restartBtn.addEventListener('click', initializeTest); // Initial setup initializeTest(); }); </script> </body> </html> ```
Drag to resize
```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</title> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f5f5f5; } .container { width: 80%; max-width: 800px; padding: 20px; background-color: white; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); text-align: center; } #words { font-size: 24px; margin: 20px 0; min-height: 60px; color: #333; } #input { font-size: 18px; padding: 10px; width: 80%; border: 2px solid #ddd; border-radius: 5px; margin-bottom: 20px; } #input:focus { outline: none; border-color: #4d90fe; } #result { font-size: 18px; margin-top: 20px; font-weight: bold; } .correct { color: #3c763d; } .current { border-bottom: 2px solid #4d90fe; } .incorrect { color: #a94442; text-decoration: underline; } #progress { margin-top: 10px; color: #666; } button { background-color: #4CAF50; color: white; border: none; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 10px 2px; cursor: pointer; border-radius: 5px; } button:hover { background-color: #45a049; } </style> </head> <body> <div class="container"> <h1>Typing Speed Test</h1> <p>Type the words below as quickly and accurately as possible.</p> <div id="words"></div> <input type="text" id="input" autocomplete="off" autofocus> <div id="result"></div> <div id="progress">Words: 0/100</div> <button id="reset">Restart Test</button> </div> <script> // Array of common words for the typing test const wordList = [ "the", "be", "to", "of", "and", "a", "in", "that", "have", "I", "it", "for", "not", "on", "with", "he", "as", "you", "do", "at", "this", "but", "his", "by", "from", "they", "we", "say", "her", "she", "or", "an", "will", "my", "one", "all", "would", "there", "their", "what", "so", "up", "out", "if", "about", "who", "get", "which", "go", "me", "when", "make", "can", "like", "time", "no", "just", "him", "know", "take", "people", "into", "year", "your", "good", "some", "could", "them", "see", "other", "than", "then", "now", "look", "only", "come", "its", "over", "think", "also", "back", "after", "use", "two", "how", "our", "work", "first", "well", "way", "even", "new", "want", "because", "any", "these", "give", "day", "most", "us", "again", "great", "free", "left", "right", "high", "small", "large", "young", "old", "fast", "slow", "long", "short", "next", "last", "early", "late", "true", "false", "open", "close", "light", "dark", "warm", "cold", "hard", "soft", "near", "far", "quick", "clean", "dirty", "easy", "difficult", "strong", "weak" ]; // Elements const wordsElement = document.getElementById('words'); const inputElement = document.getElementById('input'); const resultElement = document.getElementById('result'); const progressElement = document.getElementById('progress'); const resetButton = document.getElementById('reset'); // Test variables let currentWords = []; let currentWordIndex = 0; let startTime = null; let finished = false; let correctWords = 0; // Generate random words for the test function generateWords(count) { const words = []; for (let i = 0; i < count; i++) { const randomIndex = Math.floor(Math.random() * wordList.length); words.push(wordList[randomIndex]); } return words; } // Display the words in the UI function displayWords() { wordsElement.innerHTML = ''; currentWords.forEach((word, index) => { const wordSpan = document.createElement('span'); wordSpan.textContent = word + ' '; wordSpan.classList.add('word'); if (index === currentWordIndex) { wordSpan.classList.add('current'); } else if (index < currentWordIndex) { wordSpan.classList.add('correct'); } wordsElement.appendChild(wordSpan); }); } // Initialize the test function initTest() { currentWords = generateWords(100); currentWordIndex = 0; correctWords = 0; finished = false; startTime = null; inputElement.value = ''; inputElement.disabled = false; resultElement.textContent = ''; progressElement.textContent = 'Words: 0/100'; displayWords(); inputElement.focus(); } // Calculate WPM function calculateWPM(correctWords, timeInMinutes) { return Math.round(correctWords / timeInMinutes); } // Check the current input function checkInput() { if (finished) return; const currentWord = currentWords[currentWordIndex]; const typedText = inputElement.value.trim(); // Start the timer on first keystroke if (startTime === null && typedText.length > 0) { startTime = new Date(); } // Highlight the current word based on input const wordSpans = document.querySelectorAll('.word'); wordSpans[currentWordIndex].classList.remove('correct', 'incorrect'); if (typedText === currentWord) { wordSpans[currentWordIndex].classList.add('correct'); } else if (typedText && !currentWord.startsWith(typedText)) { wordSpans[currentWordIndex].classList.add('incorrect'); } // Check if the current word is complete if (typedText === currentWord) { currentWordIndex++; inputElement.value = ''; correctWords++; // Update progress progressElement.textContent = `Words: ${currentWordIndex}/100`; // Check if test is complete if (currentWordIndex >= currentWords.length) { finishTest(); return; } // Update current word highlighting displayWords(); } } // Finish the test function finishTest() { finished = true; inputElement.disabled = true; const endTime = new Date(); const timeElapsed = (endTime - startTime) / 1000 / 60; // Convert to minutes const wpm = calculateWPM(correctWords, timeElapsed); resultElement.innerHTML = ` Test Complete!<br> Words per minute: ${wpm}<br> Accuracy: 100%<br> Time: ${Math.round(timeElapsed * 60)} seconds `; } // Event listeners inputElement.addEventListener('input', checkInput); inputElement.addEventListener('keydown', (e) => { if (e.key === ' ') { // Prevent space from being added if the word isn't complete const currentWord = currentWords[currentWordIndex]; if (inputElement.value.trim() !== currentWord) { e.preventDefault(); } } }); resetButton.addEventListener('click', initTest); // Initialize on load initTest(); </script> </body> </html> ```
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JavaScript Typing Test</title> <style> body { font-family: 'Segoe UI', Arial, sans-serif; background: #f1f3f6; padding: 0; margin: 0; display: flex; height: 100vh; align-items: center; justify-content: center; } #container { background: #fff; border-radius: 10px; padding: 30px; max-width: 700px; box-shadow: 0 6px 22px 0 rgba(60,90,130,0.12); display: flex; flex-direction: column; align-items: center; } #words { font-size: 1.5em; letter-spacing: 1px; line-height: 1.7; margin-bottom: 20px; word-wrap: break-word; user-select: none; } .highlight { background: #d3eafd; border-radius: 3px; padding: 0 2px; } .correct { color: #34b233; } .incorrect { color: #d94343; background: #fde0de; border-radius: 3px; padding: 0 2px; } #input { padding: 10px 16px; font-size: 1em; width: 60%; max-width: 350px; margin-bottom: 18px; border: 1.5px solid #c0c0c2; border-radius: 6px; background: #f3f4f8; outline: none; transition: border .25s; } #input:focus { border: 1.5px solid #3978ec; } #info, #results { font-size: 1.1em; margin: 10px 0; } #restartBtn { display: none; padding: 10px 24px; border-radius: 5px; border: none; background: #3978ec; color: #fff; font-size: 1em; cursor: pointer; margin-top: 16px; font-weight: 500; transition: background .2s; } #restartBtn:hover { background: #2559b6; } </style> </head> <body> <div id="container"> <h2>Typing Speed Test</h2> <div id="words"></div> <input id="input" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus /> <div id="info">Type the words above as fast and accurately as you can!</div> <div id="results"></div> <button id="restartBtn">Restart</button> </div> <script> // A sample list of common English words. Expand as desired. const WORD_LIST = [ "the","be","to","of","and","a","in","that","have","I","it","for","not","on","with","he", "as","you","do","at","this","but","his","by","from","they","we","say","her","she","or","an","will", "my","one","all","would","there","their","what","so","up","out","if","about","who","get","which","go","me", "when","make","can","like","time","no","just","him","know","take","people","into","year","your","good","some", "could","them","see","other","than","then","now","look","only","come","its","over","think","also","back","after", "use","two","how","our","work","first","well","way","even","new","want","because","any","these","give","day","most","us", "man","find","here","thing","more","need","life","woman","child","down","should","call","world","school", "still","try","last","ask","never","long","might","great","right","too","big","little","place","old","tell" ]; // Generate 100 random words function getRandomWords(n) { let arr = []; for (let i = 0; i < n; i++) { arr.push(WORD_LIST[Math.floor(Math.random() * WORD_LIST.length)]); } return arr; } // State let words = []; let wordIndex = 0; let charIndex = 0; let testStarted = false; let testFinished = false; let startTime = null; let endTime = null; let correctWordCount = 0; let totalTypedChars = 0; let mistakes = 0; // DOM const wordsDisplay = document.getElementById('words'); const input = document.getElementById('input'); const info = document.getElementById('info'); const results = document.getElementById('results'); const restartBtn = document.getElementById('restartBtn'); function renderWords() { wordsDisplay.innerHTML = ''; for(let i=0; i<words.length; i++) { let span = document.createElement('span'); span.textContent = words[i]; span.id = 'word-' + i; if(i === wordIndex) span.classList.add('highlight'); wordsDisplay.appendChild(span); if(i < words.length - 1) wordsDisplay.appendChild(document.createTextNode(' ')); } } function highlightCurrentWord() { for(let i=0; i<words.length; i++) { let span = document.getElementById('word-'+i); if(i === wordIndex) { span.classList.add('highlight'); } else { span.classList.remove('highlight'); } } } function checkInput() { let currentWord = words[wordIndex]; let typed = input.value; let span = document.getElementById('word-' + wordIndex); // Remove classes span.classList.remove('correct','incorrect'); // Check for correctness so far if(currentWord.startsWith(typed)) { span.classList.remove('incorrect'); } else { span.classList.add('incorrect'); } // On space or word complete if((typed.endsWith(' ') && typed.trim().length > 0) || typed === currentWord) { const trimmedTyped = typed.trim(); // Update stats if(trimmedTyped === currentWord) { span.classList.remove('incorrect'); span.classList.add('correct'); correctWordCount++; } else { span.classList.add('incorrect'); mistakes++; } totalTypedChars += trimmedTyped.length; wordIndex++; input.value = ''; highlightCurrentWord(); if(wordIndex === words.length) { finishTest(); return; } } } function finishTest() { testFinished = true; endTime = performance.now(); input.disabled = true; let seconds = (endTime - startTime) / 1000; let wpm = Math.round((correctWordCount / seconds) * 60*100)/100; let grossWPM = Math.round((words.length / seconds) * 60*100)/100; let accuracy = Math.round((correctWordCount / words.length) * 10000) / 100; results.innerHTML = ` <b>Results:</b><br> Time Taken: ${seconds.toFixed(2)}s<br> Net WPM: <b>${wpm}</b><br> Gross WPM: <b>${grossWPM}</b><br> Words Correct: ${correctWordCount} / ${words.length}<br> Mistakes: ${mistakes}<br> Accuracy: <b>${accuracy}%</b> `; info.textContent = "Test completed! See results below."; restartBtn.style.display = "inline-block"; } // Event listeners input.addEventListener('input', function() { if(testFinished) return; if(!testStarted && input.value.length > 0) { testStarted = true; startTime = performance.now(); info.textContent = "Timer started! Keep going!"; } checkInput(); }); restartBtn.addEventListener('click', initializeTest); // Initialization function initializeTest() { words = getRandomWords(100); wordIndex = 0; charIndex = 0; testStarted = false; testFinished = false; correctWordCount = 0; totalTypedChars = 0; mistakes = 0; input.disabled = false; input.value = ''; results.innerHTML = ''; info.textContent = 'Type the words above as fast and accurately as you can!'; restartBtn.style.display = "none"; renderWords(); highlightCurrentWord(); setTimeout(()=>input.focus(),100); } // Allow pressing enter to restart input.addEventListener('keydown', function(e) { if(testFinished && e.key === 'Enter') { initializeTest(); } }); document.addEventListener('DOMContentLoaded', initializeTest); </script> </body> </html> ```
Drag to resize
```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</title> <style> body { font-family: Arial, sans-serif; text-align: center; padding: 30px; max-width: 600px; margin: 0 auto; } #word-area { font-size: 28px; margin: 20px 0; min-height: 36px; } #input-field { width: 100%; font-size: 18px; padding: 10px; } #results { margin-top: 30px; font-size: 20px; } button { margin-top: 15px; padding: 10px 20px; font-size: 16px; } </style> </head> <body> <h1>Typing Speed Test</h1> <div id="word-area"></div> <input type="text" id="input-field" disabled> <div id="results"></div> <script> const words = [ "apple", "banana", "cherry", "date", "elephant", "flower", "guitar", "happy", "island", "jungle", "kangaroo", "laptop", "mountain", "network", "orange", "picture", "question", "robot", "sunshine", "tomorrow", "umbrella", "vacation", "waterfall", "xylophone", "yellow", "zebra", "adventure", "butterfly", "celebrate", "discovery", "elephant", "freedom", "guitarist", "hamburger", "important", "journey", "knowledge", "landscape", "microsoft", "notebook", "ocean", "penguin", "queen", "rainbow", "strawberry", "telescope", "umbrella", "volcanic", "whale", "xenon", "yogurt", "zookeeper", "alligator", "birthday", "calendar", "dinosaur", "eclipse", "firefly", "galaxy", "horizon", "internet", "jellyfish", "kangaroo", "lightbulb", "mosquito", "nightfall", "ostrich", "pandemic", "quartz", "rattlesnake", "squirrel", "teapot", "umbrella", "vacuum", "waterpark", "xylophone", "yacht", "zeppelin", "abandoned", "butterfly", "catastrophe", "dangerous", "disappear", "earthquake", "fantastic", "giraffe", "hazardous", "incredible", "vaccinate", "jellyfish", "kangaroo", "labyrinth", "magnitude", "nightmare", "optimistic", "pharmaceutical", "radiation", "spectacular" ]; let shuffledWords = [], currentIndex = 0; let startTime = null, resultsDisplayed = false; function shuffle(array) { const copy = [...array]; for (let i = copy.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [copy[i], copy[j]] = [copy[j], copy[i]]; } return copy; } function startTest() { shuffledWords = shuffle(words); currentIndex = 0; startTime = null; resultsDisplayed = false; document.getElementById('word-area').textContent = shuffledWords[currentIndex]; document.getElementById('input-field').value = ''; document.getElementById('input-field').disabled = false; document.getElementById('results').innerHTML = ''; } function finishTest(duration) { if (resultsDisplayed) return; resultsDisplayed = true; const wpm = Math.round((100 / duration) * 60); document.getElementById('word-area').textContent = ''; document.getElementById('input-field').disabled = true; document.getElementById('results').innerHTML = ` <strong>Test completed!</strong><br> WPM: ${wpm}<br> Time: ${Math.round(duration * 60)} seconds<br> <button onclick="startTest()">Retry Test</button> `; } document.addEventListener("DOMContentLoaded", () => { document.getElementById('input-field').addEventListener('input', () => { if (resultsDisplayed) return; const inputField = document.getElementById('input-field'); const wordArea = document.getElementById('word-area'); const currentText = inputField.value.trim(); const currentWord = wordArea.textContent; // Start timer on first input if (!startTime && currentText.length > 0) { startTime = Date.now(); } if (currentText === currentWord && currentText !== '') { currentIndex++; inputField.value = ''; if (currentIndex < 100) { wordArea.textContent = shuffledWords[currentIndex]; } else { const duration = (Date.now() - startTime) / 1000 / 60; finishTest(duration); } } }); startTest(); }); </script> </body> </html> ```
Drag to resize
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>JavaScript Typing Test</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #f2f5f9; color: #1a1a1a; display: flex; justify-content: center; padding: 2rem; } .test-card { background: #fff; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.05); border-radius: 12px; padding: 2rem 3rem; max-width: 650px; width: 100%; } h1 { margin-top: 0; font-size: 1.6rem; } .stats { margin-bottom: 1rem; display: flex; gap: 1rem; font-size: 1.1rem; } .stats span { font-weight: 700; } .word-display { font-size: 2.2rem; line-height: 1.4; } #current-word { font-weight: 700; } #input-area { margin-top: 1.5rem; } #inputBox { width: 100%; font-size: 1.4rem; padding: 0.75rem; border-radius: 8px; border: 1px solid #ccc; outline: none; transition: box-shadow 0.2s; } .correct { color: #2ecc71; } .incorrect { color: #e74c3c; text-decoration: underline; } .completed { color: #9b9b9b; } </style> </head> <body> <div class="test-card"> <h1>100-word JavaScript Typing Test</h1> <div class="stats"> <p>Progress: <span id="progress">0/100</span></p> <p>WPM: <span id="wpm">0</span></p> <p>Time: <span id="timer">0.0s</span></p> </div> <div class="word-display" id="wordDisplay"></div> <div id="input-area"> <input id="inputBox" autocomplete="off" placeholder="Start typing here..." /> </div> </div> <script> const WORD_POOL = [ "abandon","ability","able","about","above","absent","absolute","absorb","abstract","absurd", "abuse","access","accident","account","accuse","ache","achieve","acid","across","act", "active","actor","actual","adapt","add","address","admit","adult","advance","advice", "aerobic","affair","afraid","again","age","agency","agenda","agent","agree","ahead","aim", "air","alarm","album","alcohol","alert","alike","alive","allow","almost","alone","alpha", "already","also","alter","always","amaze","among","amount","amuse","analysis","analyst", "anchor","ancient","anger","angle","angry","animal","ankle","announce","annual","anxiety", "anxious","anybody","apart","apologize","appeal","appear","apple","apply","appoint","approve", "area","argue","arise","armor","army","around","arrange","arrest","arrive","artist" ]; /* --- DOM shortcuts --- */ const $display = document.getElementById('wordDisplay'); const $inputBox = document.getElementById('inputBox'); const $progress = document.getElementById('progress'); const $wpm = document.getElementById('wpm'); const $timer = document.getElementById('timer'); /* --- Game state --- */ let words = []; let currIndex = 0; let startTime = 0; let timerHandle = 0; let gameDone = false; /* --- Helpers --- */ const randomWords = (n) => [...Array(n)].map(() => WORD_POOL[(Math.random() * WORD_POOL.length) | 0]); const resetGame = () => { currIndex = 0; gameDone = false; words = randomWords(100); startTime = 0; $inputBox.removeAttribute('disabled'); $inputBox.value = ''; $inputBox.focus(); renderWords(); updateStats(); if (timerHandle) clearInterval(timerHandle); $timer.textContent = '0.0s'; }; const renderWords = () => { let html = ''; words.forEach((w, i) => { if (i === currIndex) { html += `<span id="current-word">${w}</span> `; } else if (i < currIndex) { html += `<span class="completed">${w}</span> `; } else { html += w + ' '; } }); $display.innerHTML = html; }; const updateStats = () => { $progress.textContent = `${currIndex}/100`; if (!startTime || currIndex === 0) { $wpm.textContent = 0; return; } const minutes = (Date.now() - startTime) / 60000; const wpm = Math.round(currIndex / minutes) || 0; $wpm.textContent = wpm; }; const startTimer = () => { startTime = Date.now(); timerHandle = setInterval(() => { const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); $timer.textContent = `${elapsed}s`; }, 100); }; const endGame = () => { gameDone = true; clearInterval(timerHandle); const minutes = (Date.now() - startTime) / 60000; const wpm = Math.round(words.length / minutes) | 0; $inputBox.setAttribute('disabled', true); setTimeout(() => alert(`Finished!\nTotal time: ${((Date.now() - startTime) / 1000).toFixed(1)} s\nWPM: ${wpm}`), 10 ); }; /* --- Event Handlers --- */ $inputBox.addEventListener('keydown', (e) => { if (gameDone) return; if (!startTime) startTimer(); // first key }); $inputBox.addEventListener('input', () => { if (gameDone) return; const typed = $inputBox.value.trimEnd(); const target = words[currIndex]; const currentSpan = document.getElementById('current-word'); /* Correct so far */ if (target.startsWith(typed)) { if (typed === target) { /* move to next word */ currIndex++; updateStats(); $inputBox.value = ''; if (currIndex >= 100) { endGame(); return; } renderWords(); } else { /* partial */ currentSpan.className = ''; } } else { /* error state (optional visual cue) */ currentSpan.className = 'incorrect'; } }); /* Kick-off */ resetGame(); </script> </body> </html> ```
Drag to resize
**Typing Test Implementation** ================================ Below is a basic implementation of a typing test in JavaScript, HTML, and CSS. This test displays 100 random words and measures the user's typing speed. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Typing Test</title> <style> body { font-family: Arial, sans-serif; } #typing-test { width: 800px; margin: 40px auto; text-align: center; } #typing-input { width: 100%; height: 30px; font-size: 18px; padding: 10px; box-sizing: border-box; } #word-display { font-size: 24px; margin-bottom: 20px; } #result { font-size: 18px; margin-top: 20px; } </style> </head> <body> <div id="typing-test"> <div id="word-display"></div> <input id="typing-input" type="text" autocomplete="off"> <div id="result"></div> </div> <script> // List of words for the typing test const words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "ice cream", "jackfruit", "kiwi", "lemon", "mango", "nectarine", "orange", "pineapple", "quince", "raspberry", "strawberry", "tangerine", "ugli fruit", "victoria plum", "watermelon", "xigua", "yellow passionfruit", "zucchini"]; // Function to get a random word from the list function getRandomWord() { return words[Math.floor(Math.random() * words.length)]; } // Initialize variables let wordCount = 0; let startTime = null; let currentWord = getRandomWord(); let typedWord = ''; // Display the first word document.getElementById('word-display').innerText = currentWord; // Event listener for typing input document.getElementById('typing-input').addEventListener('input', (e) => { const input = e.target.value.trim(); // Check if the typed word is correct if (input === currentWord) { wordCount++; typedWord = ''; // Check if 100 words have been typed if (wordCount >= 100) { const endTime = new Date().getTime(); const elapsed = (endTime - startTime) / 1000 / 60; // minutes const wpm = Math.round(wordCount / elapsed); document.getElementById('result').innerText = `Your typing speed is ${wpm} words per minute.`; document.getElementById('typing-input').disabled = true; } else { // Display the next word currentWord = getRandomWord(); document.getElementById('word-display').innerText = currentWord; e.target.value = ''; } // Record the start time if it's the first word if (startTime === null) { startTime = new Date().getTime(); } } }); // Focus on the input field document.getElementById('typing-input').focus(); </script> </body> </html> ``` **How it works:** 1. The HTML structure includes a `div` to display the current word, an `input` field for typing, and a `div` to display the result. 2. The JavaScript code initializes an array of words and selects a random word to display. 3. When the user types a word and presses the correct word, the code increments the word count, records the start time if it's the first word, and displays the next random word. 4. Once 100 words have been typed, the code calculates the typing speed in words per minute (wpm) and displays the result. 5. The input field is disabled after 100 words have been typed to prevent further input. You can save this code as an HTML file and open it in a web browser to run the typing test.
Drag to resize
```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</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Courier New', monospace; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; justify-content: center; align-items: center; color: #333; } .container { background: white; border-radius: 15px; padding: 40px; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); max-width: 800px; width: 90%; } .header { text-align: center; margin-bottom: 30px; } .title { font-size: 2.5em; color: #667eea; margin-bottom: 10px; } .stats { display: flex; justify-content: space-around; margin-bottom: 30px; background: #f8f9fa; padding: 20px; border-radius: 10px; } .stat-item { text-align: center; } .stat-label { font-size: 0.9em; color: #666; margin-bottom: 5px; } .stat-value { font-size: 1.5em; font-weight: bold; color: #333; } .text-display { background: #f8f9fa; padding: 30px; border-radius: 10px; margin-bottom: 20px; font-size: 1.2em; line-height: 2; min-height: 150px; overflow: hidden; } .word { margin-right: 8px; padding: 2px 4px; border-radius: 4px; transition: all 0.2s; } .word.current { background: #667eea; color: white; } .word.correct { background: #28a745; color: white; } .word.incorrect { background: #dc3545; color: white; } .input-area { margin-bottom: 20px; } .text-input { width: 100%; padding: 15px; font-size: 1.1em; font-family: 'Courier New', monospace; border: 2px solid #ddd; border-radius: 8px; outline: none; transition: border-color 0.3s; } .text-input:focus { border-color: #667eea; } .controls { display: flex; justify-content: center; gap: 15px; margin-bottom: 20px; } .btn { padding: 12px 24px; font-size: 1em; border: none; border-radius: 8px; cursor: pointer; transition: all 0.3s; font-family: inherit; } .btn-primary { background: #667eea; color: white; } .btn-primary:hover { background: #5a67d8; } .btn-secondary { background: #6c757d; color: white; } .btn-secondary:hover { background: #5a6268; } .results { background: #e8f5e8; padding: 20px; border-radius: 10px; text-align: center; display: none; } .results h3 { color: #28a745; margin-bottom: 15px; font-size: 1.5em; } .progress-bar { width: 100%; height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden; margin-bottom: 20px; } .progress-fill { height: 100%; background: #667eea; width: 0%; transition: width 0.3s; } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="title">Typing Speed Test</h1> <p>Type the words as they appear. Test your speed with 100 words!</p> </div> <div class="progress-bar"> <div class="progress-fill" id="progressFill"></div> </div> <div class="stats"> <div class="stat-item"> <div class="stat-label">WPM</div> <div class="stat-value" id="wpm">0</div> </div> <div class="stat-item"> <div class="stat-label">Accuracy</div> <div class="stat-value" id="accuracy">100%</div> </div> <div class="stat-item"> <div class="stat-label">Time</div> <div class="stat-value" id="time">0s</div> </div> <div class="stat-item"> <div class="stat-label">Words</div> <div class="stat-value" id="wordCount">0/100</div> </div> </div> <div class="text-display" id="textDisplay"></div> <div class="input-area"> <input type="text" class="text-input" id="textInput" placeholder="Click 'Start Test' to begin..." disabled> </div> <div class="controls"> <button class="btn btn-primary" id="startBtn" onclick="startTest()">Start Test</button> <button class="btn btn-secondary" id="resetBtn" onclick="resetTest()">Reset</button> </div> <div class="results" id="results"> <h3>Test Complete!</h3> <div id="finalStats"></div> </div> </div> <script> const words = [ 'the', 'be', 'to', 'of', 'and', 'in', 'it', 'you', 'that', 'he', 'was', 'for', 'on', 'are', 'as', 'with', 'his', 'they', 'at', 'one', 'have', 'this', 'from', 'or', 'had', 'by', 'word', 'but', 'not', 'what', 'all', 'were', 'we', 'when', 'your', 'can', 'said', 'there', 'each', 'which', 'do', 'how', 'their', 'if', 'will', 'up', 'other', 'about', 'out', 'many', 'then', 'them', 'these', 'so', 'some', 'her', 'would', 'make', 'like', 'into', 'him', 'time', 'has', 'two', 'more', 'very', 'after', 'words', 'long', 'than', 'way', 'call', 'just', 'where', 'most', 'know', 'get', 'through', 'back', 'much', 'before', 'go', 'good', 'new', 'write', 'our', 'used', 'me', 'man', 'too', 'any', 'day', 'same', 'right', 'look', 'think', 'also', 'around', 'another', 'came', 'come', 'work', 'three', 'must', 'because', 'does', 'part', 'even', 'place', 'well', 'such', 'here', 'take', 'why', 'help', 'put', 'different', 'away', 'again', 'off', 'went', 'old', 'number', 'great', 'tell', 'men', 'say', 'small', 'every', 'found', 'still', 'between', 'name', 'should', 'home', 'big', 'give', 'air', 'line', 'set' ]; let currentWords = []; let currentWordIndex = 0; let currentInput = ''; let startTime = null; let isTestActive = false; let correctWords = 0; let totalTypedWords = 0; let timer = null; function generateWords() { currentWords = []; for (let i = 0; i < 100; i++) { currentWords.push(words[Math.floor(Math.random() * words.length)]); } } function displayWords() { const textDisplay = document.getElementById('textDisplay'); textDisplay.innerHTML = ''; currentWords.forEach((word, index) => { const span = document.createElement('span'); span.className = 'word'; span.textContent = word; span.id = `word-${index}`; if (index === currentWordIndex) { span.classList.add('current'); } textDisplay.appendChild(span); }); } function startTest() { generateWords(); displayWords(); currentWordIndex = 0; currentInput = ''; correctWords = 0; totalTypedWords = 0; startTime = Date.now(); isTestActive = true; const textInput = document.getElementById('textInput'); textInput.disabled = false; textInput.placeholder = 'Start typing...'; textInput.focus(); textInput.value = ''; document.getElementById('startBtn').disabled = true; document.getElementById('results').style.display = 'none'; updateStats(); startTimer(); } function resetTest() { isTestActive = false; clearInterval(timer); currentWordIndex = 0; currentInput = ''; correctWords = 0; totalTypedWords = 0; startTime = null; const textInput = document.getElementById('textInput'); textInput.disabled = true; textInput.placeholder = 'Click "Start Test" to begin...'; textInput.value = ''; document.getElementById('startBtn').disabled = false; document.getElementById('results').style.display = 'none'; document.getElementById('textDisplay').innerHTML = '<p style="text-align: center; color: #666;">Click "Start Test" to begin the typing test!</p>'; updateStats(); updateProgress(); } function startTimer() { timer = setInterval(updateStats, 100); } function updateStats() { const timeElapsed = startTime ? (Date.now() - startTime) / 1000 : 0; const minutes = timeElapsed / 60; // Calculate WPM const wpm = minutes > 0 ? Math.round(correctWords / minutes) : 0; // Calculate accuracy const accuracy = totalTypedWords > 0 ? Math.round((correctWords / totalTypedWords) * 100) : 100; document.getElementById('wpm').textContent = wpm; document.getElementById('accuracy').textContent = accuracy + '%'; document.getElementById('time').textContent = Math.round(timeElapsed) + 's'; document.getElementById('wordCount').textContent = `${correctWords}/100`; updateProgress(); } function updateProgress() { const progress = (correctWords / 100) * 100; document.getElementById('progressFill').style.width = progress + '%'; } function checkWord() { const currentWord = currentWords[currentWordIndex]; const wordElement = document.getElementById(`word-${currentWordIndex}`); totalTypedWords++; if (currentInput.trim() === currentWord) { correctWords++; wordElement.classList.remove('current'); wordElement.classList.add('correct'); } else { wordElement.classList.remove('current'); wordElement.classList.add('incorrect'); } currentWordIndex++; currentInput = ''; if (currentWordIndex < currentWords.length) { document.getElementById(`word-${currentWordIndex}`).classList.add('current'); // Scroll to current word if needed const currentWordElement = document.getElementById(`word-${currentWordIndex}`); currentWordElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } if (currentWordIndex >= 100) { finishTest(); } } function finishTest() { isTestActive = false; clearInterval(timer); const timeElapsed = (Date.now() - startTime) / 1000; const minutes = timeElapsed / 60; const wpm = Math.round(correctWords / minutes); const accuracy = Math.round((correctWords / totalTypedWords) * 100); document.getElementById('textInput').disabled = true; document.getElementById('startBtn').disabled = false; const results = document.getElementById('results'); const finalStats = document.getElementById('finalStats'); finalStats.innerHTML = ` <p><strong>Words Per Minute:</strong> ${wpm}</p> <p><strong>Accuracy:</strong> ${accuracy}%</p> <p><strong>Total Time:</strong> ${Math.round(timeElapsed)} seconds</p> <p><strong>Correct Words:</strong> ${correctWords}/100</p> `; results.style.display = 'block'; } document.getElementById('textInput').addEventListener('input', function(e) { if (!isTestActive) return; currentInput = e.target.value; // Check if user pressed space or finished typing the word if (currentInput.endsWith(' ') || currentInput === currentWords[currentWordIndex]) { if (currentInput.endsWith(' ')) { currentInput = currentInput.slice(0, -1); // Remove the space } checkWord(); e.target.value = ''; } }); document.getElementById('textInput').addEventListener('keydown', function(e) { if (!isTestActive) return; // Handle Enter key as word completion if (e.key === 'Enter') { e.preventDefault(); checkWord(); e.target.value = ''; } }); // Initialize the display resetTest(); </script> </body> </html> ``` This typing test includes: **Features:** - 100 random words from a common word list - Real-time WPM (Words Per Minute) calculation - Accuracy percentage tracking - Progress bar showing completion - Timer showing elapsed time - Visual feedback for correct/incorrect words - Responsive design with attractive styling **How to use:** 1. Click "Start Test" to begin 2. Type each word as it appears (highlighted in blue) 3. Press Space or Enter to move to the next word 4. Words turn green when correct, red when incorrect 5. Stats update in real-time 6. Test completes automatically after 100 words **Key metrics tracked:** - **WPM**: Words per minute based on correct words - **Accuracy**: Percentage of correctly typed words - **Time**: Total elapsed time - **Progress**: Visual progress bar and word counter The test uses a pool of common English words and randomly selects 100 for each test session. You can reset and start over at any time!
Drag to resize