Let's create a typing practice game with JavaScript

Shuvo - Nov 22 '21 - - Dev Community

As a programming we type a lot.

But use some random app for typing practice? Nah fam, we are creating our own typing practice game from scratch using vanilla JavaScript.

JavaScript Typing practice game demo

Video tutorial available on YouTube

Before we start here are the features our game will have:

  1. Time limit
  2. Will work with any amount of text
  3. Highlight text in green if you type correctly
  4. Highlight text in red if you type incorrectly
  5. Start game as soon as user stars typing

Okay lets start by creating our html, css and js file.
And then in the html we will have three elements:

  1. A div where we will show our text
  2. A div that will work as our progress bar
  3. A textarea where we can type
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    <div class="text"></div>
    <div class="progress-bar"></div>
    <textarea class="input" placeholder="Start Typing"></textarea>

    <script src="main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now let's style them in our css

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body{
    background-color: #ffe4c4;
    font-family: 'Gill Sans';
}

.text, .input{
    display: block;
    width: 100%;
    border: none;
    outline: none;
    padding: 1em;
    height: calc(50vh - 5px);
    font-size: 1.2em;
    font-weight: bold;
}

.progress-bar{
    height: 10px;
    background-color: rgb(0, 255, 0);
}
Enter fullscreen mode Exit fullscreen mode

Now if we open it up in our browser we will see this:
basic HTML5 project setup

Now we want to show some text in our div. We will do that in JavaScript. Because we want to wrap every character in a span.
Why? because then we can add a green or red background to the span to indicate if we've typed correct or wrong.
Lets create a function to populate the text in our div

//Any string that you want to use
const str = "Type this as fast as possible."

// Selected necessary elements
const text = document.querySelector(".text")
const input = document.querySelector(".input")
const progressBar = document.querySelector(".progress-bar")

function populateText(str){
    // str.split("") will convert our string to characters array
    // Then we can loop through them
    str.split("").map(letter => {
        const span = document.createElement("span")
        span.innerText = letter
        text.appendChild(span)
    })
}
populateText(str)
Enter fullscreen mode Exit fullscreen mode

Now you will see text is displayed and each letter is wrapped by a span
Populating text using javascript
We would need to access those spans later on. So lets store them in a array for easy access.

const str = "Type this as fast as possible."
const text = document.querySelector(".text")
const input = document.querySelector(".input")
const progressBar = document.querySelector(".progress-bar")

const charEls = []

function populateText(str){
    str.split("").map(letter => {
        const span = document.createElement("span")
        span.innerText = letter
        text.appendChild(span)

        // Adding span in array
        charEls.push(span)
    })
}
populateText(str)
Enter fullscreen mode Exit fullscreen mode

Great now when we type something in our textarea we want to get the value

const str = "Type this as fast as possible."
const text = document.querySelector(".text")
const input = document.querySelector(".input")
const progressBar = document.querySelector(".progress-bar")

const charEls = []

function populateText(str){
    str.split("").map(letter => {
        const span = document.createElement("span")
        span.innerText = letter
        text.appendChild(span)
        charEls.push(span)
    })
}
populateText(str)

input.addEventListener("keyup", () => {
    const val = input.value
    console.log(val)
})
Enter fullscreen mode Exit fullscreen mode

Get textarea value js
Now we are going to loop through all the letters inside our textarea. And for each of the letter we will compare it with the letter of our str at that index.
If they match that means we typed correct so we can add a correct class to the span at that index. Otherwise we will add wrong

input.addEventListener("keyup", () => {
    const val = input.value
    resetCharEls()
    val.split("").map((letter, i) => {
        if(letter === str[i]){
            charEls[i].classList.add("correct")
        }else{
            charEls[i].classList.add("wrong")
        }
    })
})
Enter fullscreen mode Exit fullscreen mode

Let's create those classes in our css

.correct{
    background-color: rgb(141, 252, 141);
}
.wrong{
    background-color: rgb(250, 132, 132);
}
Enter fullscreen mode Exit fullscreen mode

Now if you type something you will see text is being highlighted accordingly.
Highlight text javascript
Now we need to keep track of the error count(How many letters are not typed correctly).
And we will also check if val.length === str.length and error count is 0. If so that means we have typed everything correctly.

input.addEventListener("keyup", () => {
    const val = input.value
    resetCharEls()
    let errorCount = 0
    val.split("").map((letter, i) => {
        if(letter === str[i]){
            charEls[i].classList.add("correct")
        }else{
            charEls[i].classList.add("wrong")
            errorCount++
        }
    })
    if(val.length === str.length && errorCount === 0){
        alert("Well Done!")
    }
})
Enter fullscreen mode Exit fullscreen mode

Compare characters array js

Great!!! Now lets make the progress bar animate.
We will make the progress bars width go from 100% to 0 in 10 seconds(time is up to you) if it has a class of active. Which we will add in JavaScript.

.progress-bar.active{
    animation: 10s animate linear;
}
@keyframes animate{
    0%{
        width: 100%;
        background-color: rgb(0, 255, 0);
    }
    50%{
        width: 50%;
        background-color: rgb(238, 255, 0);
    }
    100%{
        width: 0;
        background-color: rgb(255, 0, 0);
    }
}
Enter fullscreen mode Exit fullscreen mode

And finally when the user starts typing we will add active class to our progress bar and also start a timer that will alert Time's up when the time is over.

const str = "Type this as fast as possible."
const text = document.querySelector(".text")
const input = document.querySelector(".input")
const progressBar = document.querySelector(".progress-bar")

// Timer for our game
let timer = null

const charEls = []

function populateText(str){
    str.split("").map(letter => {
        const span = document.createElement("span")
        span.innerText = letter
        text.appendChild(span)
        charEls.push(span)
    })
}
populateText(str)

function resetCharEls(){
    charEls.map(charEl => {
        charEl.classList.remove("correct")
        charEl.classList.remove("wrong")
    })
}

input.addEventListener("keyup", () => {
    // if timer is null that means the game is not started yet
    if(!timer){
        progressBar.classList.add("active")
        timer = setTimeout(() => {
            alert("Time's up!")
        }, 10000) // 10000ms = 10s, we have 10s animated duration in css also
    }
    const val = input.value
    resetCharEls()
    let errorCount = 0
    val.split("").map((letter, i) => {
        if(letter === str[i]){
            charEls[i].classList.add("correct")
        }else{
            charEls[i].classList.add("wrong")
            errorCount++
        }
    })
    if(val.length === str.length && errorCount === 0){
        alert("Well Done!")
        // clear the timer when the game is finished
        clearTimeout(timer)
    }
})
Enter fullscreen mode Exit fullscreen mode

JavaScript Complete game
And just like that we have successfully created a typing practice game with nothing but JavaScript.

You can get finished codes here

Make sure you checkout my other articles and YouTube Channel

Was it helpful? Support me on Patreon

Patreon Logo

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .