JS Quiz

You’re looking to create a JavaScript quiz tutorial! This is a fantastic way to apply core JavaScript concepts like DOM manipulation, events, arrays, objects, and conditional logic. We’ll build a simple multiple-choice quiz from scratch.

The Core Components of a JavaScript Quiz

A typical quiz involves:

  1. Questions and Answers: Stored as JavaScript data.
  2. Display Logic: Showing one question at a time.
  3. User Interaction: Handling answer selections.
  4. Scoring Logic: Checking answers and tallying points.
  5. Feedback: Telling the user if their answer was correct/incorrect.
  6. Navigation: Moving to the next question.
  7. Results: Displaying the final score.

HTML Structure for Our Quiz

Let’s set up the basic HTML. We’ll need a container for the quiz, elements to display the question, answer choices, a “next” button, and a place for the score.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Quiz</title>
    <style>
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f4f7f6; margin: 0; }
        .quiz-container {
            background-color: #ffffff;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
            width: 90%;
            max-width: 600px;
            text-align: center;
        }
        h1 { color: #333; margin-bottom: 25px; }
        #question-display {
            font-size: 1.4em;
            margin-bottom: 25px;
            color: #555;
            min-height: 60px; /* To prevent layout shift */
        }
        .answers-container {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-bottom: 25px;
        }
        .answer-button {
            background-color: #e0e0e0;
            border: 1px solid #ccc;
            padding: 12px 15px;
            font-size: 1em;
            cursor: pointer;
            border-radius: 8px;
            transition: background-color 0.2s, transform 0.1s;
            text-align: left; /* Align text to the left for better readability */
        }
        .answer-button:hover {
            background-color: #d0d0d0;
            transform: translateY(-2px);
        }
        .answer-button.selected {
            background-color: #c9e6ff;
            border-color: #007bff;
            font-weight: bold;
        }
        .answer-button.correct {
            background-color: #d4edda;
            border-color: #28a745;
            font-weight: bold;
        }
        .answer-button.incorrect {
            background-color: #f8d7da;
            border-color: #dc3545;
            font-weight: bold;
        }
        #feedback {
            margin-top: -10px; /* Adjust spacing */
            margin-bottom: 15px;
            font-weight: bold;
            min-height: 20px; /* Prevent layout shift */
        }
        #next-button {
            background-color: #007bff;
            color: white;
            padding: 12px 25px;
            font-size: 1.1em;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        #next-button:hover {
            background-color: #0056b3;
        }
        #next-button:disabled {
            background-color: #cccccc;
            cursor: not-allowed;
        }
        #score-display {
            font-size: 1.8em;
            color: #28a745;
            margin-top: 30px;
        }
    </style>
</head>
<body>
    <div class="quiz-container">
        <h1>JavaScript Quiz!</h1>
        <p id="question-display">Question will appear here.</p>
        <div class="answers-container" id="answers">
            </div>
        <p id="feedback"></p>
        <button id="next-button" disabled>Next Question</button>
        <p id="score-display" style="display: none;"></p>
    </div>

    <script>
        // JavaScript quiz logic will go here
    </script>
</body>
</html>

JavaScript Quiz Logic

Now, let’s write the JavaScript to power our quiz.

JavaScript

document.addEventListener('DOMContentLoaded', function() {
    // 1. Quiz Data
    const quizQuestions = [
        {
            question: "What does JS stand for?",
            answers: [
                { text: "Just Script", correct: false },
                { text: "JavaScript", correct: true },
                { text: "Jazzy Script", correct: false },
                { text: "Junior Script", correct: false }
            ]
        },
        {
            question: "Which keyword is used to declare a constant variable in JS?",
            answers: [
                { text: "var", correct: false },
                { text: "let", correct: false },
                { text: "const", correct: true },
                { text: "static", correct: false }
            ]
        },
        {
            question: "What is the correct way to write an array in JavaScript?",
            answers: [
                { text: "{1, 2, 3}", correct: false },
                { text: "(1, 2, 3)", correct: false },
                { text: "[1, 2, 3]", correct: true },
                { text: "<1, 2, 3>", correct: false }
            ]
        },
        {
            question: "Which method is used to add an element to the end of an array?",
            answers: [
                { text: "append()", correct: false },
                { text: "push()", correct: true },
                { text: "addToEnd()", correct: false },
                { text: "last()", correct: false }
            ]
        }
    ];

    // 2. DOM Element References
    const questionDisplay = document.getElementById('question-display');
    const answersContainer = document.getElementById('answers');
    const feedbackParagraph = document.getElementById('feedback');
    const nextButton = document.getElementById('next-button');
    const scoreDisplay = document.getElementById('score-display');

    // 3. Quiz State Variables
    let currentQuestionIndex = 0;
    let score = 0;
    let selectedAnswerButton = null; // To keep track of the selected answer

    // 4. Function to Load a Question
    function loadQuestion() {
        // Reset previous state
        resetQuizState();

        if (currentQuestionIndex < quizQuestions.length) {
            const questionData = quizQuestions[currentQuestionIndex];
            questionDisplay.textContent = `${currentQuestionIndex + 1}. ${questionData.question}`;

            questionData.answers.forEach(answer => {
                const button = document.createElement('button');
                button.textContent = answer.text;
                button.classList.add('answer-button');
                button.dataset.correct = answer.correct; // Store correct state as a data attribute
                answersContainer.appendChild(button);

                button.addEventListener('click', selectAnswer);
            });
            nextButton.disabled = true; // Disable next button until an answer is selected
        } else {
            // Quiz finished
            showResults();
        }
    }

    // 5. Function to Handle Answer Selection
    function selectAnswer(event) {
        // If an answer was already selected, deselect it visually
        if (selectedAnswerButton) {
            selectedAnswerButton.classList.remove('selected');
        }

        const clickedButton = event.target;
        clickedButton.classList.add('selected');
        selectedAnswerButton = clickedButton; // Store reference to the selected button

        // Enable the next button as an answer has been selected
        nextButton.disabled = false;
        feedbackParagraph.textContent = ""; // Clear any previous feedback

        // Optional: Provide immediate feedback if desired (but for a quiz, usually after 'Next')
        // const isCorrect = JSON.parse(clickedButton.dataset.correct);
        // feedbackParagraph.textContent = isCorrect ? "Correct!" : "Incorrect!";
        // feedbackParagraph.style.color = isCorrect ? "green" : "red";
    }

    // 6. Function to Check Answer and Advance
    function checkAnswerAndAdvance() {
        if (!selectedAnswerButton) {
            alert("Please select an answer before proceeding!");
            return;
        }

        // Disable all answer buttons to prevent re-selection
        Array.from(answersContainer.children).forEach(button => {
            button.disabled = true;
        });

        const isCorrect = JSON.parse(selectedAnswerButton.dataset.correct); // Convert string 'true'/'false' to boolean

        // Provide visual feedback (correct/incorrect styling)
        if (isCorrect) {
            selectedAnswerButton.classList.add('correct');
            feedbackParagraph.textContent = "Correct!";
            feedbackParagraph.style.color = "green";
            score++;
        } else {
            selectedAnswerButton.classList.add('incorrect');
            feedbackParagraph.textContent = "Incorrect.";
            feedbackParagraph.style.color = "red";
            // Also show the correct answer
            Array.from(answersContainer.children).forEach(button => {
                if (JSON.parse(button.dataset.correct)) {
                    button.classList.add('correct'); // Highlight the correct answer
                }
            });
        }

        nextButton.textContent = (currentQuestionIndex === quizQuestions.length - 1) ? "Show Results" : "Next Question";
        nextButton.disabled = false; // Ensure next button is enabled to advance
        
        // Wait a moment before loading the next question or showing results
        setTimeout(() => {
            currentQuestionIndex++;
            loadQuestion();
        }, 1500); // Wait 1.5 seconds before moving to next question/results
    }

    // 7. Function to Reset Quiz State for Next Question
    function resetQuizState() {
        answersContainer.innerHTML = ''; // Clear previous answer buttons
        feedbackParagraph.textContent = ''; // Clear feedback
        feedbackParagraph.style.color = ''; // Reset feedback color
        nextButton.textContent = 'Next Question';
        nextButton.disabled = true;
        selectedAnswerButton = null; // Reset selected answer
    }

    // 8. Function to Show Final Results
    function showResults() {
        questionDisplay.style.display = 'none';
        answersContainer.style.display = 'none';
        feedbackParagraph.style.display = 'none';
        nextButton.style.display = 'none';

        scoreDisplay.textContent = `Quiz Complete! You scored ${score} out of ${quizQuestions.length}!`;
        scoreDisplay.style.display = 'block';
    }

    // Event Listener for the Next Button
    nextButton.addEventListener('click', checkAnswerAndAdvance);

    // Initial load of the first question
    loadQuestion();
});

Explanation of the JavaScript Logic:

  1. quizQuestions Array: This array of objects holds all our quiz data. Each object has a question string and an answers array. Each answer object has text and a correct boolean.
  2. DOM References: We get references to the HTML elements we need to manipulate.
  3. State Variables:
    • currentQuestionIndex: Tracks which question we’re currently on.
    • score: Keeps track of the user’s correct answers.
    • selectedAnswerButton: A variable to store the button element the user clicked, so we can access its properties later.
  4. loadQuestion():
    • Clears previous answers and feedback.
    • Checks if there are more questions. If not, it calls showResults().
    • Updates questionDisplay with the current question.
    • Iterates through questionData.answers using forEach().
    • For each answer, it document.createElement('button'), sets its textContent, adds the answer-button CSS class, and importantly, sets a data-correct attribute (a custom attribute to store the correct state) which makes it easy to retrieve the correctness.
    • Appends the created button to the answersContainer.
    • Attaches a click event listener to each answer button, calling selectAnswer.
    • Disables the nextButton until an answer is selected.
  5. selectAnswer(event):
    • This function runs when an answer button is clicked. event.target refers to the specific button clicked.
    • It manages the visual selected class, ensuring only one button looks selected at a time.
    • Enables the nextButton because an answer has now been chosen.
  6. checkAnswerAndAdvance():
    • First, it checks if an answer was actually selected.
    • It disables all answer buttons to prevent further clicks for the current question.
    • It retrieves the correct state from the selectedAnswerButton.dataset.correct (remember to JSON.parse it as data attributes are always strings).
    • Updates the score if correct.
    • Applies correct or incorrect CSS classes for visual feedback and updates the feedbackParagraph.
    • If the answer was incorrect, it also highlights the correct answer’s button.
    • Changes the text of the nextButton to “Show Results” if it’s the last question.
    • Uses setTimeout() to pause briefly (1.5 seconds) before incrementing currentQuestionIndex and calling loadQuestion() again, giving the user time to see the feedback.
  7. resetQuizState(): Clears the previous answers, feedback, and resets the “next” button’s state, preparing the UI for the next question.
  8. showResults(): Hides the quiz elements and displays the final score.
  9. Event Listener for nextButton: The nextButton‘s click event directly calls checkAnswerAndAdvance().
  10. Initial Call: loadQuestion() is called once DOMContentLoaded to start the quiz.

This setup provides a robust, interactive, and user-friendly JavaScript quiz experience. You can easily extend it by adding more questions, different types of feedback, timers, or more complex scoring mechanisms.

Share the Post:

Related Posts