Learn how to build an interactive trivia quiz game using HTML, CSS, and JavaScript with this step-by-step guide.
Table of Contents
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 namedstyles.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 innerdiv
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 classanswer
and adata-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 classstart-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 withsans-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 of500px
. box-shadow
adds a subtle shadow effect.text-align: center
centers text, andtransition: 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 aheader
. The font size is2rem
, the color is dark gray, and there's20px
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 a20px
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, and10px
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 a15px
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, andborder-radius: 12px
rounds the corners.- The button becomes clickable with
cursor: pointer
, and transitions onbackground-color
andtransform
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 usingjustify-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 of1rem
.
.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 of5px
and a light gray background (#ddd
).#progress
fills the progress bar, starting withwidth: 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 theoptions
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 thequestions
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 callsloadQuestion()
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 inlocalStorage
), 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:
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 😊