Building an Interactive Quiz App with HTML, CSS, and JavaScript

In this blog post, we'll walk through the process of creating an engaging quiz application using HTML, CSS, and JavaScript. We'll be utilizing the QuizAPI to fetch quiz questions, making our app dynamic and expandable.
Introduction
Quizzes are a great way to engage users and test knowledge on various topics. Our quiz app will fetch questions from an external API, present them to the user, and provide immediate feedback on their answers. Let's dive into the code and see how it all comes together!
The HTML Structure
First, let's look at the HTML structure of our app:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz Master</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Quiz Master</h1>
<div id="score">Score: <span id="score-value">0</span></div>
<div id="question"></div>
<div id="answers"></div>
<div id="result"></div>
<button id="next">Next Question</button>
</div>
<script src="script.js"></script>
</body>
</html>
This structure provides the backbone of our app, with placeholders for the question, answers, result, and score.
Styling with CSS
Next, let's add some style to our app. Create a file named styles.css
and add the following:
/* Reset default styles */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
line-height: 1.6;
color: #333;
background-color: #f0f2f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.container {
width: 100%;
max-width: 600px;
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
}
h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 1.5rem;
font-weight: 700;
}
#question {
font-size: 1.2rem;
margin-bottom: 1.5rem;
color: #34495e;
font-weight: 400;
}
#answers {
display: grid;
gap: 1rem;
}
button {
padding: 0.8rem;
background-color: #3498db;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s, transform 0.1s;
font-size: 1rem;
font-weight: 500;
}
button:hover {
background-color: #2980b9;
}
button:active {
transform: scale(0.98);
}
#result {
margin-top: 1.5rem;
font-weight: 600;
text-align: center;
}
#next {
display: none;
margin-top: 1.5rem;
width: 100%;
background-color: #2ecc71;
}
#next:hover {
background-color: #27ae60;
}
#score {
text-align: center;
margin-bottom: 1rem;
font-size: 1.2rem;
font-weight: 600;
color: #2c3e50;
}
@media (max-width: 480px) {
.container {
padding: 1.5rem;
}
#question {
font-size: 1.1rem;
}
button {
padding: 0.7rem;
}
}
This CSS provides a clean, modern look for our quiz app and ensures it's responsive across different device sizes.
Adding Functionality with JavaScript
Now, let's bring our app to life with JavaScript. Create a file named script.js
and add the following code:
const questionEl = document.getElementById('question');
const answersEl = document.getElementById('answers');
const resultEl = document.getElementById('result');
const nextBtn = document.getElementById('next');
const scoreEl = document.getElementById('score-value');
let currentQuestion;
let score = 0;
async function fetchQuestion() {
try {
const response = await fetch('https://quizapi.io/api/v1/questions?apiKey=YOUR_API_KEY&limit=1');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data[0];
} catch (error) {
console.error('Error fetching question:', error);
return null;
}
}
function displayQuestion(question) {
currentQuestion = question;
questionEl.textContent = question.question;
answersEl.innerHTML = '';
for (const [key, value] of Object.entries(question.answers)) {
if (value) {
const button = document.createElement('button');
button.textContent = value;
button.addEventListener('click', () => checkAnswer(key));
answersEl.appendChild(button);
}
}
resultEl.textContent = '';
nextBtn.style.display = 'none';
}
function checkAnswer(selectedKey) {
const correctKey = Object.keys(currentQuestion.correct_answers).find(
key => currentQuestion.correct_answers[key] === 'true'
);
const buttons = answersEl.getElementsByTagName('button');
for (let button of buttons) {
button.disabled = true;
}
if (selectedKey === correctKey.replace('_correct', '')) {
resultEl.textContent = 'Correct! Well done!';
resultEl.style.color = '#2ecc71';
score++;
scoreEl.textContent = score;
} else {
resultEl.textContent = 'Incorrect. The correct answer was: ' +
currentQuestion.answers[correctKey.replace('_correct', '')];
resultEl.style.color = '#e74c3c';
}
nextBtn.style.display = 'block';
}
nextBtn.addEventListener('click', loadQuestion);
async function loadQuestion() {
const question = await fetchQuestion();
if (question) {
displayQuestion(question);
} else {
questionEl.textContent = 'Failed to load question. Please try again later.';
}
}
// Initial load
loadQuestion();
This JavaScript code handles fetching questions from the API, displaying them to the user, checking answers, and updating the score.
Using the QuizAPI
Our app uses the QuizAPI to fetch quiz questions. To use this API:
- Sign up for a free account at https://quizapi.io/
- Once logged in, navigate to the API Keys section to get your API key
- Replace
'YOUR_API_KEY'
in thefetchQuestion
function with your actual API key
The QuizAPI offers various parameters to customize your quiz questions, such as category, difficulty, and number of questions. Feel free to explore these options to enhance your quiz app further!
Conclusion
And there you have it! We've created a responsive, interactive quiz app using HTML, CSS, and JavaScript, integrated with a third-party API for dynamic content. This app demonstrates key concepts such as:
- Asynchronous JavaScript with
async/await
- DOM manipulation
- Event handling
- API integration
- Responsive design with CSS
Feel free to expand on this foundation by adding features like a timer, multiple categories, or a leaderboard.
Happy coding!
Comments
No approved comments available yet