Hello and welcome to today’s tutorial. In today’s tutorial, we will be creating a typing test project. For this project, we will be needing HTML, CSS and Javascript.
This project would be very helpful for javascript intermediates. If you are looking for more projects to practice javascript, do check out this playlist. This playlist consists of around 50 projects along with source code. Anyone from beginners to experts can use them to practice their skills.
Now coming to our project, we will create a typing test application. This project generates a random test sentence on every window load event. The user has to click on the ‘Start Test’ button and start typing in the provided text area. The characters entered correctly are turned into green colour while wrong ones are turned into red.
The application shows two stats. The first is a countdown timer of 60seconds, and the second is the mistakes counter. For every mistake the user makes while typing, the mistake counter increase by one.
Other Tutorials You Might Like:
The typing test stops either when the user clicks on the ‘Stop test’ button or when the timer reaches 0. After the test ends, a result is displayed. The result consists of two stats first is the typing speed in wpm and the second is the accuracy in terms of percentage.
Video Tutorial:
I have a video version of this tutorial on my youtube channel. If you are interested in code along with me, you can check out the video down below. Also, do subscribe to my youtube channel, where I post new tutorials every alternate day.
Project Folder Structure:
Before we start to code, let us check out the project folder structure. We name the project folder as a Typing test
. Inside this project, we have three files an HTML document, a stylesheet and a script file. We name these files index.html
, style.css
and script.js
respectively.
HTML:
We begin with the HTML code. Copy the code provided below and paste it into our HTML document.
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Typing Test</title> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet" /> <!-- Stylesheet --> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="container"> <div class="stats"> <p>Time: <span id="timer">0s</span></p> <p>Mistakes: <span id="mistakes">0</span></p> </div> <div id="quote" onmousedown="return false" onselectstart="return false" ></div> <textarea rows="3" id="quote-input" placeholder="Type here when the test starts.." ></textarea> <button id="start-test" onclick="startTest()">Start Test</button> <button id="stop-test" onclick="displayResult()">Stop Test</button> <div class="result"> <h3>Result</h3> <div class="wrapper"> <p>Accuracy: <span id="accuracy"></span></p> <p>Speed: <span id="wpm"></span></p> </div> </div> </div> <!-- Script --> <script src="script.js"></script> </body> </html>
CSS:
Next, we add some styles to our typing test app. For this we need CSS. Now copy the code below and paste it into your stylesheet.
* { padding: 0; margin: 0; box-sizing: border-box; font-family: "Poppins", sans-serif; } body { background-color: #3066f6; } .container { width: 80vmin; padding: 50px 30px; background-color: #ffffff; position: absolute; transform: translate(-50%, -50%); top: 50%; left: 50%; border-radius: 10px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); } .stats { text-align: right; font-size: 18px; margin-bottom: 30px; } .stats span { font-weight: 600; } #quote { text-align: justify; margin: 50px 0 30px 0; } textarea { resize: none; width: 100%; border-radius: 5px; padding: 10px 5px; font-size: 16px; } button { float: right; margin-top: 20px; background-color: #3066f6; color: #ffffff; border: none; padding: 10px 30px; border-radius: 5px; font-size: 18px; } .result { margin-top: 40px; display: none; } .result h3 { text-align: center; margin-bottom: 20px; font-size: 22px; } .wrapper { display: flex; justify-content: space-around; } .wrapper span { font-weight: 600; } .success { color: #44b267; } .fail { color: #e81c4e; }
Javascript:
Lastly, we add functionality to this project by using javascript. Copy the code below and paste it into your javascript file.
//Random Quotes Api URL const quoteApiUrl = "https://api.quotable.io/random?minLength=80&maxLength=100"; const quoteSection = document.getElementById("quote"); const userInput = document.getElementById("quote-input"); let quote = ""; let time = 60; let timer = ""; let mistakes = 0; //Display random quotes const renderNewQuote = async () => { //Fetch contents from url const response = await fetch(quoteApiUrl); //Store response let data = await response.json(); //Access quote quote = data.content; //Array of characters in the quote let arr = quote.split("").map((value) => { //wrap the characters in a span tag return "<span class='quote-chars'>" + value + "</span>"; }); //join array for displaying quoteSection.innerHTML += arr.join(""); }; //Logic for comparing input words with quote userInput.addEventListener("input", () => { let quoteChars = document.querySelectorAll(".quote-chars"); //Create an arrat from received span tags quoteChars = Array.from(quoteChars); //array of user input characters let userInputChars = userInput.value.split(""); //loop through each character in quote quoteChars.forEach((char, index) => { //Check if char(quote character) = userInputChars[index](input character) if (char.innerText == userInputChars[index]) { char.classList.add("success"); } //If user hasn't entered anything or backspaced else if (userInputChars[index] == null) { //Remove class if any if (char.classList.contains("success")) { char.classList.remove("success"); } else { char.classList.remove("fail"); } } //If user enter wrong character else { //Checks if we alreasy have added fail class if (!char.classList.contains("fail")) { //increment and display mistakes mistakes += 1; char.classList.add("fail"); } document.getElementById("mistakes").innerText = mistakes; } //Returns true if all the characters are entered correctly let check = quoteChars.every((element) => { return element.classList.contains("success"); }); //End test if all characters are correct if (check) { displayResult(); } }); }); //Update Timer on screen function updateTimer() { if (time == 0) { //End test if timer reaches 0 displayResult(); } else { document.getElementById("timer").innerText = --time + "s"; } } //Sets timer const timeReduce = () => { time = 60; timer = setInterval(updateTimer, 1000); }; //End Test const displayResult = () => { //display result div document.querySelector(".result").style.display = "block"; clearInterval(timer); document.getElementById("stop-test").style.display = "none"; userInput.disabled = true; let timeTaken = 1; if (time != 0) { timeTaken = (60 - time) / 100; } document.getElementById("wpm").innerText = (userInput.value.length / 5 / timeTaken).toFixed(2) + " wpm"; document.getElementById("accuracy").innerText = Math.round( ((userInput.value.length - mistakes) / userInput.value.length) * 100 ) + " %"; }; //Start Test const startTest = () => { mistakes = 0; timer = ""; userInput.disabled = false; timeReduce(); document.getElementById("start-test").style.display = "none"; document.getElementById("stop-test").style.display = "block"; }; window.onload = () => { userInput.value = ""; document.getElementById("start-test").style.display = "block"; document.getElementById("stop-test").style.display = "none"; userInput.disabled = true; renderNewQuote(); };
And that’s it. Your typing test app is now ready. If you have any issues while creating this project, you can download the source code by clicking the ‘Download code’ button below. Also, don’t forget to drop your suggestions and feedback in the comments below.
Keep up the good work