Let's create a typing practice game with JavaScript
Tags: webdev, javascript, html, tutorial
Published: 2021-11-22 11:43:15

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5v563uolon39k8z1zy22.gif)
> [Video tutorial](https://www.youtube.com/watch?v=uWAn5TFZY_E) 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
```html
<!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>
```
Now let's style them in our css
```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);
}
```
Now if we open it up in our browser we will see this:
![basic HTML5 project setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4je6r6m11lk2p3trpgs.png)

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
```js
//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)
```
Now you will see text is displayed and each letter is wrapped by a `span`
![Populating text using javascript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egcyjdsxhgsn61vu6meu.png)
We would need to access those spans later on. So lets store them in a array for easy access.
```js
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)
```
Great now when we type something in our textarea we want to get the value
```js
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)
})
```
![Get textarea value js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbsxqz2f3x6d14awcxv5.png)
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`

```js
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")
        }
    })
})
```
Let's create those classes in our css
```css
.correct{
    background-color: rgb(141, 252, 141);
}
.wrong{
    background-color: rgb(250, 132, 132);
}
```
Now if you type something you will see text is being highlighted accordingly.
![Highlight text javascript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/som78upzogbulf6g06dv.png)
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.
```js
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!")
    }
})
```
![Compare characters array js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ky0fr9aqx1uz5wn3t32m.png)
 
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.
```css
.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);
    }
}
```
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.
```js
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)
    }
})
```
![JavaScript Complete game](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ac38fzc1mzlapjg0t6fr.png)
And just like that we have successfully created a typing practice game with nothing but JavaScript.

### You can get [finished codes here](https://github.com/0shuvo0/js-typing-game)

## Make sure you checkout my other articles and YouTube Channel
{% user 0shuvo0 %}
## Was it helpful? Support me on Patreon
[![Patreon Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vnw8g7vs5pok3jwgtgv.png)](https://www.patreon.com/0shuvo0)