Open In App

Create a Quiz App with Timer using HTML CSS and JavaScript

Last Updated : 29 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this tutorial, we’ll guide you through the process of building an engaging Quiz App with a built-in timer, utilizing HTML, CSS, and JavaScript. This application is designed to present users with a curated set of questions, each accompanied by a countdown timer, providing an interactive and time-bound quiz experience. Additionally, the app keeps track of users’ progress, creating an immersive and dynamic quiz environment. Let’s get started on creating a captivating Quiz App that combines functionality with an intuitive user interface.

Preview

z13

Preview of Final output

Approach

  • First, create a Web page basic structure using HTML tags like buttons and heading for landing page, a button to Start Quiz, and <h1> Geeks for Geeks</h1> tags for heading text. Also, use divs and span for outer body structure along with relevant Class names and IDs.
  • Style the web page using the class names with CSS properties like font weight for text margins, padding to add space, text-align for alignment, and display type for display styling of individual elements.
  • In JavaScript, create a function that triggers the Start Quiz. When the user starts the quiz, they will get multiple questions, one after another. When the user validates the answers, they can move on to the next question. There are a series of questions hard-coded in the JavaScript file.
  • At the end, when all the questions are completed, the user will get a high score page where they can view their score.

Example: This example describes the basic implementation of the Quiz App with Timer using HTML, CSS, and JavaScript.

Javascript




// script.js
 
let questions = [
    {
        prompt: `Inside which HTML
                 element do we put
                 the JavaScript?`,
        options: [
            "<javascript>",
            "<js>",
            "<script>",
            "<scripting>",
        ],
        answer: "<script>",
    },
 
    {
        prompt: `How do you call a
                 function named
                 myFunction?`,
        options: [
            "call myFunction()",
            "myFunction()",
            "call function myFunction",
            "Call.myFunction",
        ],
        answer: "myFunction()",
    },
 
    {
        prompt: `How does a for loop
                 start?`,
        options: [
            "for (i = 0; i <= 5; i++)",
            "for (i = 0; i <= 5)",
            "for i = 1 to 5",
            " for (i <= 5; i++)",
        ],
        answer: "for (i = 0; i <= 5; i++)",
    },
 
    {
        prompt: `In JavaScript, which
                 of the following is
                 a logical operator?`,
        options: ["|", "&&", "%", "/"],
        answer: "&&",
    },
 
    {
        prompt: `A named element in a
                 JavaScript program that
                 is used to store and
                 retrieve data is a _____.`,
        options: [
            "method",
            "assignment operator",
            "letiable",
            "string",
        ],
        answer: "letiable",
    },
];
 
// Get Dom Elements
 
let questionsEl =
    document.querySelector(
        "#questions"
    );
let timerEl =
    document.querySelector("#timer");
let choicesEl =
    document.querySelector("#options");
let submitBtn = document.querySelector(
    "#submit-score"
);
let startBtn =
    document.querySelector("#start");
let nameEl =
    document.querySelector("#name");
let feedbackEl = document.querySelector(
    "#feedback"
);
let reStartBtn =
    document.querySelector("#restart");
 
// Quiz's initial state
let currentQuestionIndex = 0;
let time = questions.length * 15;
let timerId;
 
// Start quiz and hide frontpage
 
function quizStart() {
    timerId = setInterval(
        clockTick,
        1000
    );
    timerEl.textContent = time;
    let landingScreenEl =
        document.getElementById(
            "start-screen"
        );
    landingScreenEl.setAttribute(
        "class",
        "hide"
    );
    questionsEl.removeAttribute(
        "class"
    );
    getQuestion();
}
 
// Loop through array of questions and
// Answers and create list with buttons
function getQuestion() {
    let currentQuestion =
        questions[currentQuestionIndex];
    let promptEl =
        document.getElementById(
            "question-words"
        );
    promptEl.textContent =
        currentQuestion.prompt;
    choicesEl.innerHTML = "";
    currentQuestion.options.forEach(
        function (choice, i) {
            let choiceBtn =
                document.createElement(
                    "button"
                );
            choiceBtn.setAttribute(
                "value",
                choice
            );
            choiceBtn.textContent =
                i + 1 + ". " + choice;
            choiceBtn.onclick =
                questionClick;
            choicesEl.appendChild(
                choiceBtn
            );
        }
    );
}
 
// Check for right answers and deduct
// Time for wrong answer, go to next question
 
function questionClick() {
    if (
        this.value !==
        questions[currentQuestionIndex]
            .answer
    ) {
        time -= 10;
        if (time < 0) {
            time = 0;
        }
        timerEl.textContent = time;
        feedbackEl.textContent = `Wrong! The correct answer was
        ${questions[currentQuestionIndex].answer}.`;
        feedbackEl.style.color = "red";
    } else {
        feedbackEl.textContent =
            "Correct!";
        feedbackEl.style.color =
            "green";
    }
    feedbackEl.setAttribute(
        "class",
        "feedback"
    );
    setTimeout(function () {
        feedbackEl.setAttribute(
            "class",
            "feedback hide"
        );
    }, 2000);
    currentQuestionIndex++;
    if (
        currentQuestionIndex ===
        questions.length
    ) {
        quizEnd();
    } else {
        getQuestion();
    }
}
 
// End quiz by hiding questions,
// Stop timer and show final score
 
function quizEnd() {
    clearInterval(timerId);
    let endScreenEl =
        document.getElementById(
            "quiz-end"
        );
    endScreenEl.removeAttribute(
        "class"
    );
    let finalScoreEl =
        document.getElementById(
            "score-final"
        );
    finalScoreEl.textContent = time;
    questionsEl.setAttribute(
        "class",
        "hide"
    );
}
 
// End quiz if timer reaches 0
 
function clockTick() {
    time--;
    timerEl.textContent = time;
    if (time <= 0) {
        quizEnd();
    }
}
 
// Save score in local storage
// Along with users' name
 
function saveHighscore() {
    let name = nameEl.value.trim();
    if (name !== "") {
        let highscores =
            JSON.parse(
                window.localStorage.getItem(
                    "highscores"
                )
            ) || [];
        let newScore = {
            score: time,
            name: name,
        };
        highscores.push(newScore);
        window.localStorage.setItem(
            "highscores",
            JSON.stringify(highscores)
        );
        alert(
            "Your Score has been Submitted"
        );
    }
}
 
// Save users' score after pressing enter
 
function checkForEnter(event) {
    if (event.key === "Enter") {
        saveHighscore();
        alert(
            "Your Score has been Submitted"
        );
    }
}
nameEl.onkeyup = checkForEnter;
 
// Save users' score after clicking submit
 
submitBtn.onclick = saveHighscore;
 
// Start quiz after clicking start quiz
 
startBtn.onclick = quizStart;


Javascript




// highScore.js
 
let scoresBtn = document.querySelector(
    "#view-high-scores"
);
 
// Rank previous scores in order by
// Retrieving scores from localStorage
 
function printHighscores() {
    let highscores =
        JSON.parse(
            window.localStorage.getItem(
                "highscores"
            )
        ) || [];
    highscores.sort(function (a, b) {
        return b.score - a.score;
    });
    highscores.forEach(function (
        score
    ) {
        let liTag =
            document.createElement(
                "li"
            );
        liTag.textContent =
            score.name +
            " - " +
            score.score;
        let olEl =
            document.getElementById(
                "highscores"
            );
        olEl.appendChild(liTag);
    });
}
 
// Clear previous scores when users click clear
function clearHighscores() {
    window.localStorage.removeItem(
        "highscores"
    );
    window.location.reload();
}
document.getElementById(
    "clear"
).onclick = clearHighscores;
 
printHighscores();


HTML




<!--highscore.html-->
 
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width,
                   initial-scale=1.0" />
    <link rel="stylesheet"
          href="./style.css" />
       <script src="./highScore.js"></script>
    <title>Code Quiz - High Scores</title>
</head>
 
<body>
    <div class="scores">
        <h1>Highscores</h1>
        <ol id="highscores"></ol>
        <a href="index.html">
            <button>
                Re-Start
            </button>
        </a>
        <button id="clear">
            Clear Highscores
        </button>
    </div>
</body>
 
</html>


HTML




<!--index.html-->
 
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width,
                   initial-scale=1.0" />
    <link rel="stylesheet"
          href="./style.css" />
    <title>Code Quiz</title>
</head>
 
<body>
    <div class="containerNew">
        <header>
            <div>
                <a href="./highscore.html">
                    <button class="scores-header"
                            id="view-high-scores">
                        View High Scores
                    </button>
                </a>
            </div>
 
            <div class="timer">
                <p>
                    Time:
                    <span id="timer">
                        0
                    </span>
                </p>
            </div>
        </header>
 
        <main class="quiz">
            <div id="quiz-start">
                <div class="landing"
                     id="start-screen">
                    <h1 id="top">
                        GeeksforGeeks
                    </h1>
                    <h1>
                        Coding Quiz Challenge
                    </h1>
                    <p>
                        Try to answer the following
                        code-related questions with
                        in the time limit. Keep in
                        mind that incorrect answers
                        will penalize your score/time
                        by ten seconds!
                    </p>
                    <button id="start">
                        Start Quiz
                    </button>
                </div>
            </div>
 
            <div class="hide" id="questions">
                <h2 id="question-words"></h2>
                <div class="options" id="options">
                </div>
            </div>
 
            <div class="hide" id="quiz-end">
                <h2>All Done!</h2>
                <p>Your final score is:
                    <span id="score-final">
                    </span>
                </p>
                <p>
                    Please enter your name:
                    <input type="text"
                           id="name"
                           max="3" />
                    <button id="submit-score">
                        Submit
                    </button>
                </p>
            </div>
 
            <div id="feedback"
                 class="feedback hide">
            </div>
        </main>
    </div>
    <script src="./script.js"></script>
</body>
 
</html>


CSS




/* Style.css */
 
* {
    font-family: Georgia, Times, "Times New Roman", serif;
}
 
.quiz,
.scores {
    margin: 50px auto 0 auto;
    max-width: 400px;
}
 
#top {
    color: green;
}
 
.containerNew {
    border: 5px solid;
    position: absolute;
    top: 50%;
    left: 50%;
    height: 580px;
    width: 50%;
    transform: translate(-50%, -50%);
    padding: 10px;
}
 
p {
    margin: 15px 15px;
}
 
.landing {
    text-align: center;
}
 
.scoresHeader {
    position: absolute;
    top: 15px;
    left: 15px;
}
 
.timer {
    position: absolute;
    top: 15px;
    right: 15px;
}
 
button {
    display: inline-block;
    margin: 10px;
    cursor: pointer;
    color: #fff;
    background-color: #52865a;
    border-radius: 5px;
    border: 0;
    padding: 20px;
}
 
button:hover {
    background-color: #2a8d12;
}
 
.options button {
    display: block;
}
 
input[type="text"] {
    font-size: 100%;
}
 
.hide {
    display: none;
}
 
.feedback {
    font-style: bold;
    font-size: 120%;
    margin-top: 20px;
    padding-top: 15px;
    color: #fff;
    border-top: 2px solid #4B0082;
}
 
ol {
    padding-left: 15px;
    max-height: 600px;
    overflow: auto;
}
 
li {
    padding: 5px;
    list-style: decimal inside none;
}
 
li:nth-child(odd) {
    background-color: #dfdae7;
}
 
@media screen and (max-width: 768px) {
    .containerNew {
        width: 80%;
    }
}
 
@media screen and (max-width: 575px) {
    .containerNew {
        width: 90%;
    }
 
    .quiz,
    .scores {
        max-width: 90%;
    }
}


Output:

2c2b529e-af18-488f-9860-692f21e25d1c

Final Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads