Create Trivia Quiz Game using HTML, CSS, and JavaScript

Faraz

By Faraz -

Learn how to build an interactive trivia quiz game using HTML, CSS, and JavaScript with this step-by-step guide.


create-trivia-quiz-game-using-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

Are you looking to build a fun and interactive trivia quiz game? In this tutorial, you'll learn how to create a trivia quiz using HTML, CSS, and JavaScript. This is a great beginner project to sharpen your coding skills and create something engaging.

Whether you're a student or a budding web developer, this project will help you understand how to work with JavaScript functions, DOM manipulation, and event handling.

Prerequisites

Before we get started, make sure you know the basics of:

  • HTML (to create the structure of the game),
  • CSS (to style the game for a good user experience), and
  • JavaScript (for adding logic and interactivity).

A simple text editor like VS Code or Notepad++ will be perfect for writing the code.

Source Code

Step 1 (HTML Code):

Start by creating a basic HTML structure for the game. The HTML file will hold the elements, such as the question, answer options, and buttons. Here's a breakdown of each part:

<!DOCTYPE html>

This declaration defines the document type and version of HTML (HTML5 in this case).

<html lang="en">

This tag defines the beginning of the HTML document, and lang="en" specifies that the language is English.

<head>

The <head> section contains meta-information about the document, such as the character set, viewport settings, and external resources like stylesheets.

  • <meta charset="UTF-8">: Specifies the character encoding for the document as UTF-8, which supports most characters and symbols.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Ensures that the page is responsive and adjusts to different screen sizes, particularly for mobile devices.
  • <title>Trivia Quiz Game</title>: Sets the title of the page, which appears in the browser tab.
  • <link rel="stylesheet" href="styles.css">: Links an external CSS file named styles.css to style the content of the page.

<body>

This is where the content of the web page is defined. It includes a game container, card, question area, and buttons for answering trivia questions.

<div class="game-container">

A wrapper div that holds the entire game layout. The class game-container is used to style this section.

<div class="game-card">

This div holds all the game components, such as the title, question, answers, and game status (score, high score, time).

<header>

Contains the main title of the game:

  • <h1>Trivia Challenge</h1>: Displays the heading for the game.

<div class="game-content">

This div contains the actual gameplay components, including the progress bar, question, and answers.

  • Progress Bar:
    • <div class="progress-bar">: Represents a visual indicator for progress.
    • <div id="progress"></div>: The inner div is where progress will be visually represented, typically by changing its width dynamically with JavaScript.
  • Question Section:
    • <div class="question-container">: Holds the question and its category.
    • <p id="category" class="category-text">Category: Science</p>: Displays the current category of the trivia question.
    • <h2 id="question">What is the largest planet in our solar system?</h2>: Displays the trivia question.
  • Answer Buttons:
    • <div class="answers-container">: Holds the four answer options.
    • Four <button> elements represent each answer option. Each button has a class answer and a data-id attribute for identifying the answer (1, 2, 3, or 4). The text inside each button is the possible answer.
  • Status Bar:
    • <div class="status-bar">: Contains the game's score, high score, and time left for answering the question.
    • <p>Score: <span id="score">0</span></p>: Displays the player's current score.
    • <p>High Score: <span id="high-score">0</span></p>: Displays the high score.
    • <p>Time Left: <span id="time">30</span> seconds</p>: Displays the time left to answer the current question.
  • Start Button:
    • <button id="start" class="start-btn">Start Game</button>: A button to start the game, styled with the class start-btn.

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

This tag includes an external JavaScript file (script.js), which will contain the game logic, such as handling button clicks, updating the score, and controlling the timer.

Step 2 (CSS Code):

Next, you need to style the game so it looks clean and user-friendly. Here's a breakdown of the CSS code:

Global Styles

* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}
  • The * selector targets all elements and resets the default margin and padding to zero.
  • box-sizing: border-box makes sure that padding and border widths are included in the total width and height of an element.

body Styles

body {
	font-family: 'Poppins', sans-serif;
	height: 100vh;
	background: linear-gradient(135deg, #6b73ff, #000dff);
	display: flex;
	justify-content: center;
	align-items: center;
}
  • The body uses the 'Poppins' font with sans-serif fallback.
  • height: 100vh ensures that the body takes the full height of the viewport.
  • The background is a gradient with a 135-degree angle transitioning from blue (#6b73ff) to dark blue (#000dff).
  • display: flex; justify-content: center; align-items: center; centers content horizontally and vertically.

.game-container Styles

.game-container {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 100%;
}
  • .game-container is a flex container to center content.
  • width: 100% ensures it takes up the full width of the parent container.

.game-card Styles

.game-card {
	background-color: #fff;
	border-radius: 20px;
	padding: 30px;
	max-width: 500px;
	width: 100%;
	box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
	text-align: center;
	transition: transform 0.3s;
}
  • .game-card is styled like a card with a white background and rounded corners (border-radius: 20px).
  • It has padding of 30px and is limited to a maximum width of 500px.
  • box-shadow adds a subtle shadow effect.
  • text-align: center centers text, and transition: transform 0.3s; ensures smooth animation for transformations.

header h1 Styles

header h1 {
	font-size: 2rem;
	color: #333;
	margin-bottom: 20px;
}
  • This styles the h1 inside a header. The font size is 2rem, the color is dark gray, and there's 20px space below it.

.question-container h2 Styles

.question-container h2 {
	color: #444;
	margin-bottom: 20px;
}
  • The h2 element in .question-container is given a medium gray color and has a 20px margin at the bottom.

.category-text Styles

.category-text {
	color: #6b73ff;
	font-size: 1rem;
	margin-bottom: 10px;
}
  • .category-text has a blue color (#6b73ff), 1rem font size, and 10px margin at the bottom.

.answers-container Styles

.answers-container {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 15px;
	margin-bottom: 20px;
}
  • The .answers-container is styled as a grid with two columns (1fr 1fr) and a 15px gap between grid items.
  • A 20px margin at the bottom separates it from other content.

button.answer Styles

button.answer {
	background-color: #6b73ff;
	color: #fff;
	border: none;
	padding: 15px;
	border-radius: 12px;
	font-size: 1.1rem;
	cursor: pointer;
	transition: background-color 0.3s ease, transform 0.3s;
}
  • This styles the .answer buttons with a blue background (#6b73ff) and white text.
  • padding: 15px provides space inside the button, and border-radius: 12px rounds the corners.
  • The button becomes clickable with cursor: pointer, and transitions on background-color and transform for smooth hover effects.

button.answer:hover Styles

button.answer:hover {
	background-color: #4e57d9;
	transform: scale(1.05);
}
  • On hover, the .answer button changes its background color to a darker blue and slightly scales up (transform: scale(1.05)).

.correct and .incorrect Button Styles

button.correct {
	background-color: #4caf50;
}

button.incorrect {
	background-color: #f44336;
}
  • The .correct button gets a green background (#4caf50), and .incorrect gets a red background (#f44336).

.start-btn Styles

.start-btn {
	background-color: #ff6363;
	color: #fff;
	border: none;
	padding: 12px 20px;
	border-radius: 12px;
	cursor: pointer;
	font-size: 1rem;
	transition: background-color 0.3s;
}
  • The .start-btn is styled with a red background (#ff6363), white text, rounded corners, and a button-like appearance with padding and no border.
  • Transitions on background color are applied for smooth hover effects.

.start-btn:hover Styles

.start-btn:hover {
	background-color: #ff4545;
}
  • On hover, the .start-btn changes its background color to a darker red (#ff4545).

.status-bar Styles

.status-bar {
	margin-top: 20px;
	display: flex;
	justify-content: space-around;
	align-items: center;
	color: #444;
}
  • The .status-bar is a flex container that evenly spaces items using justify-content: space-around. It has a medium gray color for the text.

.status-bar p Styles

.status-bar p {
	font-size: 1rem;
}
  • The paragraph inside .status-bar has a font size of 1rem.

.progress-bar and #progress Styles

.progress-bar {
	height: 5px;
	background-color: #ddd;
	border-radius: 5px;
	overflow: hidden;
	margin-bottom: 20px;
}

#progress {
	width: 0%;
	height: 100%;
	background-color: #6b73ff;
	transition: width 0.3s ease-in-out;
}
  • .progress-bar creates a bar with a height of 5px and a light gray background (#ddd).
  • #progress fills the progress bar, starting with width: 0% and expanding as needed. It has a blue background and smooth transitions (transition: width 0.3s ease-in-out).
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

body {
	font-family: 'Poppins', sans-serif;
	height: 100vh;
	background: linear-gradient(135deg, #6b73ff, #000dff);
	display: flex;
	justify-content: center;
	align-items: center;
}

.game-container {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 100%;
}

.game-card {
	background-color: #fff;
	border-radius: 20px;
	padding: 30px;
	max-width: 500px;
	width: 100%;
	box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
	text-align: center;
	transition: transform 0.3s;
}

header h1 {
	font-size: 2rem;
	color: #333;
	margin-bottom: 20px;
}

.question-container h2 {
	color: #444;
	margin-bottom: 20px;
}

.category-text {
	color: #6b73ff;
	font-size: 1rem;
	margin-bottom: 10px;
}

.answers-container {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 15px;
	margin-bottom: 20px;
}

button.answer {
	background-color: #6b73ff;
	color: #fff;
	border: none;
	padding: 15px;
	border-radius: 12px;
	font-size: 1.1rem;
	cursor: pointer;
	transition: background-color 0.3s ease, transform 0.3s;
}

button.answer:hover {
	background-color: #4e57d9;
	transform: scale(1.05);
}

button.correct {
	background-color: #4caf50;
}

button.incorrect {
	background-color: #f44336;
}

.start-btn {
	background-color: #ff6363;
	color: #fff;
	border: none;
	padding: 12px 20px;
	border-radius: 12px;
	cursor: pointer;
	font-size: 1rem;
	transition: background-color 0.3s;
}

.start-btn:hover {
	background-color: #ff4545;
}

.status-bar {
	margin-top: 20px;
	display: flex;
	justify-content: space-around;
	align-items: center;
	color: #444;
}

.status-bar p {
	font-size: 1rem;
}

.progress-bar {
	height: 5px;
	background-color: #ddd;
	border-radius: 5px;
	overflow: hidden;
	margin-bottom: 20px;
}

#progress {
	width: 0%;
	height: 100%;
	background-color: #6b73ff;
	transition: width 0.3s ease-in-out;
} 

Step 3 (JavaScript Code):

Now, it’s time to add the JavaScript to make your quiz game interactive. Let's break it down:

Questions Array:

  • The questions array holds the quiz questions. Each question object contains:
    • category: The category of the question (e.g., "Science").
    • question: The actual question text.
    • options: A list of possible answers.
    • answer: The index of the correct answer in the options array.

Shuffle Function:

function shuffle(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}
  • This function randomly shuffles the elements of an array. It is used to shuffle both the questions and the answer options to ensure a different order in each game.

Game Variables:

  • shuffledQuestions: Stores a shuffled version of the questions array.
  • currentQuestionIndex: Tracks the index of the current question being displayed.
  • score: Keeps the player's score.
  • timeLeft: The remaining time for the quiz (starts at 60 seconds).
  • timerInterval: A reference to the interval used for the countdown timer.
  • progress: Keeps track of the game progress (percentage of questions completed).

DOM Elements:

The script accesses various HTML elements using document.getElementById() and document.querySelectorAll() to update the UI:

  • categoryElem, questionElem: Display the question's category and text.
  • answerButtons: A collection of buttons representing the answer options.
  • scoreElem, highScoreElem: Show the player's current score and the high score.
  • timeElem: Displays the remaining time.
  • progressElem: Shows the progress bar for the quiz.
  • startButton: The button to start the game.

Starting the Game:

function startGame() {
    score = 0;
    currentQuestionIndex = 0;
    scoreElem.innerText = score;
    startButton.disabled = true;
    timeLeft = 60;
    timeElem.innerText = timeLeft;
    shuffledQuestions = [...questions];
    shuffle(shuffledQuestions);
    timerInterval = setInterval(updateTimer, 1000);
    loadQuestion();
}
  • startGame() resets the score and question index, disables the start button, sets the timer, shuffles the questions, and starts the countdown. It then calls loadQuestion() to display the first question.

Loading a Question:

function loadQuestion() {
    const questionData = shuffledQuestions[currentQuestionIndex];
    categoryElem.innerText = `Category: ${questionData.category}`;
    questionElem.innerText = questionData.question;
    const shuffledAnswers = [...questionData.options];
    shuffle(shuffledAnswers);
    answerButtons.forEach((btn, index) => {
        btn.innerText = shuffledAnswers[index];
        btn.classList.remove('correct', 'incorrect');
        btn.disabled = false;
    });
    progress = ((currentQuestionIndex + 1) / shuffledQuestions.length) * 100;
    progressElem.style.width = `${progress}%`;
}
  • This function updates the question and options on the UI. The answer buttons are reset to ensure they are not disabled or colored from the previous question. It also updates the progress bar.

Timer Function:

function updateTimer() {
    timeLeft--;
    timeElem.innerText = timeLeft;
    if (timeLeft === 0) {
        clearInterval(timerInterval);
        endGame();
    }
}
  • This function decreases the remaining time by 1 second. When the time runs out, the endGame() function is called.

Checking the Answer:

function checkAnswer(selectedIndex) {
    const questionData = shuffledQuestions[currentQuestionIndex];
    const correctAnswerText = questionData.options[questionData.answer];
    if (answerButtons[selectedIndex].innerText === correctAnswerText) {
        answerButtons[selectedIndex].classList.add('correct');
        score++;
    } else {
        answerButtons[selectedIndex].classList.add('incorrect');
    }
    scoreElem.innerText = score;
    answerButtons.forEach(btn => btn.disabled = true); 
    setTimeout(nextQuestion, 1000);
}
  • checkAnswer() checks if the selected answer is correct by comparing the selected button's text to the correct answer. The correct button is highlighted, and the score is updated. Then, all buttons are disabled to prevent multiple answers from being clicked.

Moving to the Next Question:

function nextQuestion() {
    currentQuestionIndex++;
    if (currentQuestionIndex < shuffledQuestions.length) {
        loadQuestion();
    } else {
        endGame();
    }
}
  • After a delay, the game moves to the next question or ends the game if all questions have been answered.

Ending the Game:

function endGame() {
    clearInterval(timerInterval);
    alert(`Game Over! Your score: ${score}`);
    const highScore = localStorage.getItem('highScore') || 0;
    if (score > highScore) {
        localStorage.setItem('highScore', score);
        highScoreElem.innerText = score;
    }
    startButton.disabled = false;
}
  • endGame() stops the timer, shows the final score, checks if the player beat the high score (stored in localStorage), and updates it if needed. It then re-enables the start button.

Event Listeners:

  • The game is started by clicking the startButton.
  • Each answer button listens for a click event and calls checkAnswer() to verify the player's choice.
const questions = [
    {
        category: "Science",
        question: "What is the largest planet in our solar system?",
        options: ["Earth", "Mars", "Jupiter", "Saturn"],
        answer: 2
    },
    {
        category: "History",
        question: "Who was the first President of the United States?",
        options: ["Abraham Lincoln", "George Washington", "Thomas Jefferson", "John Adams"],
        answer: 1
    },
    {
        category: "General Knowledge",
        question: "Which company is known for the iPhone?",
        options: ["Microsoft", "Apple", "Google", "Samsung"],
        answer: 1
    },
    {
        category: "Geography",
        question: "Which is the longest river in the world?",
        options: ["Nile", "Amazon", "Yangtze", "Mississippi"],
        answer: 0
    },
    {
        category: "Entertainment",
        question: "Which movie won the Oscar for Best Picture in 2020?",
        options: ["Parasite", "1917", "Joker", "Ford v Ferrari"],
        answer: 0
    },
    {
        category: "Sports",
        question: "Which country won the FIFA World Cup in 2018?",
        options: ["Germany", "Argentina", "France", "Brazil"],
        answer: 2
    },
    {
        category: "Technology",
        question: "What does HTTP stand for?",
        options: ["HyperText Transfer Protocol", "HyperText Transfer Program", "Hyper Transfer Protocol", "HyperText Transport Program"],
        answer: 0
    },
    {
        category: "Literature",
        question: "Who wrote 'Pride and Prejudice'?",
        options: ["Emily Brontë", "George Eliot", "Jane Austen", "Charles Dickens"],
        answer: 2
    },
    {
        category: "Science",
        question: "What is the chemical symbol for Gold?",
        options: ["Au", "Ag", "Gd", "Pt"],
        answer: 0
    },
    {
        category: "Mathematics",
        question: "What is the value of Pi (π) to two decimal places?",
        options: ["3.12", "3.14", "3.16", "3.18"],
        answer: 1
    },
    {
        category: "Space",
        question: "Which planet is known as the Red Planet?",
        options: ["Mars", "Venus", "Mercury", "Jupiter"],
        answer: 0
    },
    {
        category: "History",
        question: "When did World War II end?",
        options: ["1939", "1941", "1945", "1950"],
        answer: 2
    },
    {
        category: "Science",
        question: "What gas do plants absorb from the atmosphere?",
        options: ["Oxygen", "Carbon Dioxide", "Nitrogen", "Hydrogen"],
        answer: 1
    }
];

function shuffle(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

let shuffledQuestions = [];
let currentQuestionIndex = 0;
let score = 0;
let timeLeft = 60;
let timerInterval;
let progress = 0;

const categoryElem = document.getElementById('category');
const questionElem = document.getElementById('question');
const answerButtons = document.querySelectorAll('.answer');
const scoreElem = document.getElementById('score');
const highScoreElem = document.getElementById('high-score');
const timeElem = document.getElementById('time');
const progressElem = document.getElementById('progress');
const startButton = document.getElementById('start');

if (localStorage.getItem('highScore')) {
    highScoreElem.innerText = localStorage.getItem('highScore');
}

function startGame() {
    score = 0;
    currentQuestionIndex = 0;
    scoreElem.innerText = score;
    startButton.disabled = true;
    timeLeft = 60;
    timeElem.innerText = timeLeft;
    shuffledQuestions = [...questions];
    shuffle(shuffledQuestions); 
    timerInterval = setInterval(updateTimer, 1000);
    loadQuestion();
}

function loadQuestion() {
    const questionData = shuffledQuestions[currentQuestionIndex];
    categoryElem.innerText = `Category: ${questionData.category}`;
    questionElem.innerText = questionData.question;

    const shuffledAnswers = [...questionData.options];
    shuffle(shuffledAnswers);

    answerButtons.forEach((btn, index) => {
        btn.innerText = shuffledAnswers[index];
        btn.classList.remove('correct', 'incorrect');
        btn.disabled = false;
    });

    progress = ((currentQuestionIndex + 1) / shuffledQuestions.length) * 100;
    progressElem.style.width = `${progress}%`;
}

function updateTimer() {
    timeLeft--;
    timeElem.innerText = timeLeft;
    if (timeLeft === 0) {
        clearInterval(timerInterval);
        endGame();
    }
}

function checkAnswer(selectedIndex) {
    const questionData = shuffledQuestions[currentQuestionIndex];
    const correctAnswerText = questionData.options[questionData.answer];

    if (answerButtons[selectedIndex].innerText === correctAnswerText) {
        answerButtons[selectedIndex].classList.add('correct');
        score++;
    } else {
        answerButtons[selectedIndex].classList.add('incorrect');
    }

    scoreElem.innerText = score;
    answerButtons.forEach(btn => btn.disabled = true); 
    setTimeout(nextQuestion, 1000);
}

function nextQuestion() {
    currentQuestionIndex++;
    if (currentQuestionIndex < shuffledQuestions.length) {
        loadQuestion();
    } else {
        endGame();
    }
}

function endGame() {
    clearInterval(timerInterval);
    alert(`Game Over! Your score: ${score}`);
    const highScore = localStorage.getItem('highScore') || 0;
    if (score > highScore) {
        localStorage.setItem('highScore', score);
        highScoreElem.innerText = score;
    }
    startButton.disabled = false;
}

startButton.addEventListener('click', startGame);
answerButtons.forEach((btn, index) => {
    btn.addEventListener('click', () => checkAnswer(index));
});

Final Output:

create-trivia-quiz-game-using-html-css-and-javascript.gif

Conclusion:

Creating a trivia quiz game using HTML, CSS, and JavaScript is a fun way to practice your coding skills. By following this simple guide, you can build a fully functional quiz game that you can expand and customize. Whether you’re learning JavaScript or looking for an interesting project, this trivia game will help you improve your coding ability and boost your confidence as a developer.

Now it’s time to create your own quiz game, add more questions, and challenge your friends!

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺