Speed Typing Test Game using HTML, CSS and JavaScript

Share your love
Welcome to Coding Torque! Are you ready to take your coding skills to the next level? Today, we are going to create a Speed Typing Test using HTML, CSS and JavaScript. This project will challenge your coding abilities and help you hone your JavaScript skills. With this project, you will be able to create a fun and interactive typing game that can be shared with friends and family. So let’s get started!

Before we start, here are some more apps using javascript you might like to create:

1. Movie App using JavaScript

2. GIF Searching App using JavaScript

3. Currency Converter using JavaScript

 

I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.

HTML CodeĀ 

Starter Template

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSS -->
    <link rel="stylesheet" href="style.css">

    <title>Typing Speed Test using JavaScript - Coding Torque</title>
</head>

<body>
    <!-- Further code here -->

    <script src="script.js"></script>
</body>

</html>

Paste the below code in your <body> tag.

<div class="wrapper">
    <input type="text" class="input-field">
    <div class="content-box">
        <div class="typing-text">
            <p></p>
        </div>
        <div class="content">
            <ul class="result-details">
                <li class="timeLeft">
                    <p>time Left:</p>
                    <span><b>60</b>s</span>
                </li>
                <li class="errors">
                    <p>Errors:</p>
                    <span>0</span>
                </li>
                <li class="wpm">
                    <p>WPM:</p>
                    <span>0</span>
                </li>
                <li class="cpm">
                    <p>CPM:</p>
                    <span>0</span>
                </li>
            </ul>
            <button>Test Again</button>
        </div>
    </div>
</div>

Output Till Now

CSS CodeĀ 

Create a fileĀ style.css and paste the code below.

/* Import Google Font - Poppins */
@import url("https://fonts.googleapis.com/css2?family=Merriweather:wght@400;500;600;700&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Merriweather", sans-serif;
}

body {
  display: flex;
  padding: 0 10px;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: #0f172a;
}

::selection {
  color: #fff;
  background: deepskyblue;
}

.wrapper {
  width: 770px;
  padding: 35px;
  background: #0f172a;
  color: #f1f5f9;
  border-radius: 10px;
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.05);
}

.wrapper .input-field {
  opacity: 0;
  z-index: -999;
  position: absolute;
}

.wrapper .content-box {
  padding: 13px 20px 0;
  border-radius: 10px;
  border: 1px solid #bfbfbf;
}

.content-box .typing-text {
  overflow: hidden;
  max-height: 256px;
}

.typing-text::-webkit-scrollbar {
  width: 0;
}

.typing-text p {
  font-size: 25px;
  text-align: justify;
  letter-spacing: 1px;
}

.typing-text p span {
  position: relative;
}

.typing-text p span.correct {
  color: lawngreen;
}

.typing-text p span.incorrect {
  color: #cb3439;
  outline: 1px solid #fff;
  background: #ffc0cb;
  border-radius: 4px;
}

.typing-text p span.active {
  color: deepskyblue;
}

.typing-text p span.active::before {
  position: absolute;
  content: "";
  height: 2px;
  width: 100%;
  bottom: 0;
  left: 0;
  opacity: 0;
  border-radius: 5px;
  background: deepskyblue;
  animation: blink 1s ease-in-out infinite;
}

@keyframes blink {
  50% {
    opacity: 1;
  }
}

.content-box .content {
  margin-top: 17px;
  display: flex;
  padding: 12px 0;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid #bfbfbf;
  line-break: auto;
}

.content button {
  outline: none;
  border: none;
  width: 105px;
  color: #fff;
  padding: 8px 0;
  font-size: 16px;
  cursor: pointer;
  border-radius: 5px;
  background: deepskyblue;
  transition: transform 0.3s ease;
}

.content button:active {
  transform: scale(0.97);
}

.content .result-details {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  width: calc(100% - 140px);
  justify-content: space-between;
}

.result-details li {
  display: flex;
  height: 20px;
  list-style: none;
  position: relative;
  align-items: center;
}

.result-details li:not(:first-child) {
  padding-left: 22px;
  border-left: 1px solid #bfbfbf;
}

.result-details li p {
  font-size: 19px;
}

.result-details li span {
  display: block;
  font-size: 20px;
  margin-left: 10px;
}

li span b {
  font-weight: 500;
}

li:not(:first-child) span {
  font-weight: 500;
}

.errors span {
  color: #facc15;
}

.timeLeft span {
  color: #cb3439;
}

Output Till Now

Speed Typing Test Game using javascript

JavaScript CodeĀ 

Create a fileĀ script.jsĀ and paste the code below.
const paragraphs = [
    "One dollar and eighty-seven cents. That was all. And sixty cents of it was in pennies. Pennies saved one and two at a time by bulldozing the grocer and the vegetable man and the butcher until oneā€™s cheeks burned with the silent imputation of parsimony that such close dealing implied. One dollar and eighty-seven cents. And the next day would be Christmas...",
    "There was a leak in the boat. Nobody had yet noticed it, and nobody would for the next couple of hours. This was a problem since the boat was heading out to sea and while the leak was quite small at the moment, it would be much larger when it was ultimately discovered. John had planned it exactly this way.",
    "The paper was blank. It shouldn't have been. There should have been writing on the paper, at least a paragraph if not more. The fact that the writing wasn't there was frustrating. Actually, it was even more than frustrating. It was downright distressing.", "The coin hovered in the air, spinning over and over again. It reached its peak and began to descend. Both boys were pleading with it to land a certain way but the coin had already made up its mind on what it was going to do.",
    "I'll talk to you tomorrow in more detail at our meeting, but I think I've found a solution to our problem. It's not exactly legal, but it won't land us in jail for the rest of our lives either. Are you willing to take the chance? Monroe asked his partner over the phone.",
    "There was a time when he would have embraced the change that was coming. In his youth, he sought adventure and the unknown, but that had been years ago. He wished he could go back and learn to find the excitement that came with change but it was useless. That curiosity had long left him to where he had come to loathe anything that put him out of his comfort zone."
];

const typingText = document.querySelector(".typing-text p"),
    inpField = document.querySelector(".wrapper .input-field"),
    tryAgainBtn = document.querySelector(".content button"),
    timeTag = document.querySelector(".timeLeft span b"),
    errorTag = document.querySelector(".errors span"),
    wpmTag = document.querySelector(".wpm span"),
    cpmTag = document.querySelector(".cpm span");

let timer,
    maxTime = 60,
    timeLeft = maxTime,
    charIndex = errors = isTyping = 0;

function loadParagraph() {
    const ranIndex = Math.floor(Math.random() * paragraphs.length);
    typingText.innerHTML = "";
    paragraphs[ranIndex].split("").forEach(char => {
        let span = `<span>${char}</span>`
        typingText.innerHTML += span;
    });
    typingText.querySelectorAll("span")[0].classList.add("active");
    document.addEventListener("keydown", () => inpField.focus());
    typingText.addEventListener("click", () => inpField.focus());
}

function initTyping() {
    let characters = typingText.querySelectorAll("span");
    let typedChar = inpField.value.split("")[charIndex];
    if (charIndex < characters.length - 1 && timeLeft > 0) {
        if (!isTyping) {
            timer = setInterval(initTimer, 1000);
            isTyping = true;
        }
        if (typedChar == null) {
            if (charIndex > 0) {
                charIndex--;
                if (characters[charIndex].classList.contains("incorrect")) {
                    errors--;
                }
                characters[charIndex].classList.remove("correct", "incorrect");
            }
        } else {
            if (characters[charIndex].innerText == typedChar) {
                characters[charIndex].classList.add("correct");
            } else {
                errors++;
                characters[charIndex].classList.add("incorrect");
            }
            charIndex++;
        }
        characters.forEach(span => span.classList.remove("active"));
        characters[charIndex].classList.add("active");

        let wpm = Math.round(((charIndex - errors) / 5) / (maxTime - timeLeft) * 60);
        wpm = wpm < 0 || !wpm || wpm === Infinity ? 0 : wpm;

        wpmTag.innerText = wpm;
        errorTag.innerText = errors;
        cpmTag.innerText = charIndex - errors;
    } else {
        clearInterval(timer);
        inpField.value = "";
    }
}

function initTimer() {
    if (timeLeft > 0) {
        timeLeft--;
        timeTag.innerText = timeLeft;
        let wpm = Math.round(((charIndex - errors) / 5) / (maxTime - timeLeft) * 60);
        wpmTag.innerText = wpm;
    } else {
        clearInterval(timer);
    }
}

function resetTest() {
    loadParagraph();
    clearInterval(timer);
    timeLeft = maxTime;
    charIndex = errors = isTyping = 0;
    inpField.value = "";
    timeTag.innerText = timeLeft;
    wpmTag.innerText = 0;
    errorTag.innerText = 03;
    cpmTag.innerText = 0;
}

loadParagraph();
inpField.addEventListener("input", initTyping);
tryAgainBtn.addEventListener("click", resetTest);
Written by: Piyush Patil
If you have any doubts or any project ideas feel free to Contact Us
Hope you find this post helpfulšŸ’–
Share your love

2 Comments

Comments are closed.