This article is about building a simple quiz web application using HTML, CSS and pure JavaScript, I plan on making this short and simple as possible. An image of final result can been seen below;
firstly, we'd need to create 3 files,
index.html //to hold our html codes
index.css //to hold our css codes
index.js //to hold our javascript codes
//feel free to name the files whatever you like, but this article I'd be going with those names above...
Let start by adding the following codes to the html file
<body onload="NextQuestion(0)">
<main>
<!-- creating a modal for when quiz ends -->
<div class="modal-container" id="score-modal">
<div class="modal-content-container">
<h1>Congratulations, Quiz Completed.</h1>
<div class="grade-details">
<p>Attempts : 10</p>
<p>Wrong Answers : <span id="wrong-answers"></span></p>
<p>Right Answers : <span id="right-answers"></span></p>
<p>Grade : <span id="grade-percentage"></span>%</p>
<p ><span id="remarks"></span></p>
</div>
<div class="modal-button-container">
<button onclick="closeScoreModal()">Continue</button>
</div>
</div>
</div>
<!-- end of modal of quiz details-->
<div class="game-quiz-container">
<div class="game-details-container">
<h1>Score : <span id="player-score"></span> / 10</h1>
<h1> Question : <span id="question-number"></span> / 10</h1>
</div>
<div class="game-question-container">
<h1 id="display-question"></h1>
</div>
<div class="game-options-container">
<div class="modal-container" id="option-modal">
<div class="modal-content-container">
<h1>Please Pick An Option</h1>
<div class="modal-button-container">
<button onclick="closeOptionModal()">Continue</button>
</div>
</div>
</div>
<span>
<input type="radio" id="option-one" name="option" class="radio" value="optionA" />
<label for="option-one" class="option" id="option-one-label"></label>
</span>
<span>
<input type="radio" id="option-two" name="option" class="radio" value="optionB" />
<label for="option-two" class="option" id="option-two-label"></label>
</span>
<span>
<input type="radio" id="option-three" name="option" class="radio" value="optionC" />
<label for="option-three" class="option" id="option-three-label"></label>
</span>
<span>
<input type="radio" id="option-four" name="option" class="radio" value="optionD" />
<label for="option-four" class="option" id="option-four-label"></label>
</span>
</div>
<div class="next-button-container">
<button onclick="handleNextQuestion()">Next Question</button>
</div>
</div>
</main>
<script src="index.js"></script>
</body>
That'll be all for the HTML file. Next, we'll be adding the following code to the CSS file to give the HTML some styling.
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body{
height: 100%;
}
body{
font-family: 'Montserrat', serif;
}
main{
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: black;
background: url('../assets/background_image.jpg');
background-color : black;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
.game-quiz-container{
width: 40rem;
height: 30rem;
background-color: lightgray;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
border-radius: 30px;
}
.game-details-container{
width: 80%;
height: 4rem;
display: flex;
justify-content: space-around;
align-items: center;
}
.game-details-container h1{
font-size: 1.2rem;
}
.game-question-container{
width: 80%;
height: 8rem;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid darkgray;
border-radius: 25px;
}
.game-question-container h1{
font-size: 1.1rem;
text-align: center;
padding: 3px;
}
.game-options-container{
width: 80%;
height: 12rem;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-around;
}
.game-options-container span{
width: 45%;
height: 3rem;
border: 2px solid darkgray;
border-radius: 20px;
overflow: hidden;
}
span label{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: transform 0.3s;
font-weight: 600;
color: rgb(22, 22, 22);
}
span label:hover{
-ms-transform: scale(1.12);
-webkit-transform: scale(1.12);
transform: scale(1.12);
color: white;
}
input[type="radio"] {
position: relative;
display: none;
}
input[type=radio]:checked ~ .option {
background: paleturquoise;
}
.next-button-container{
width: 50%;
height: 3rem;
display: flex;
justify-content: center;
}
.next-button-container button{
width: 8rem;
height: 2rem;
border-radius: 10px;
background: none;
color: rgb(25, 25, 25);
font-weight: 600;
border: 2px solid gray;
cursor: pointer;
outline: none;
}
.next-button-container button:hover{
background-color: rgb(143, 93, 93);
}
.modal-container{
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
flex-direction: column;
align-items: center;
justify-content: center;
-webkit-animation: fadeIn 1.2s ease-in-out;
animation: fadeIn 1.2s ease-in-out;
}
.modal-content-container{
height: 20rem;
width: 25rem;
background-color: rgb(43, 42, 42);
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
border-radius: 25px;
}
.modal-content-container h1{
font-size: 1.3rem;
height: 3rem;
color: lightgray;
text-align: center;
}
.grade-details{
width: 15rem;
height: 10rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.grade-details p{
color: white;
text-align: center;
}
.modal-button-container{
height: 2rem;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.modal-button-container button{
width: 10rem;
height: 2rem;
background: none;
outline: none;
border: 1px solid rgb(252, 242, 241);
color: white;
font-size: 1.1rem;
cursor: pointer;
border-radius: 20px;
}
.modal-button-container button:hover{
background-color: rgb(83, 82, 82);
}
@media(min-width : 300px) and (max-width : 350px){
.game-quiz-container{
width: 90%;
height: 80vh;
}
.game-details-container h1{
font-size: 0.8rem;
}
.game-question-container{
height: 6rem;
}
.game-question-container h1{
font-size: 0.9rem;
}
.game-options-container span{
width: 90%;
height: 2.5rem;
}
.game-options-container span label{
font-size: 0.8rem;
}
.modal-content-container{
width: 90%;
height: 25rem;
}
.modal-content-container h1{
font-size: 1.2rem;
}
}
@media(min-width : 350px) and (max-width : 700px){
.game-quiz-container{
width: 90%;
height: 80vh;
}
.game-details-container h1{
font-size: 1rem;
}
.game-question-container{
height: 8rem;
}
.game-question-container h1{
font-size: 0.9rem;
}
.game-options-container span{
width: 90%;
}
.modal-content-container{
width: 90%;
height: 25rem;
}
.modal-content-container h1{
font-size: 1.2rem;
}
}
@keyframes fadeIn {
from {opacity: 0;}
to {opacity:1 ;}
}
@-webkit-keyframes fadeIn {
from {opacity: 0;}
to {opacity: 1;}
}
If you successfully followed along correctly up to this point, you should be having the below image on your page;
Yes, there are no questions yet, don't worry our friend JavaScript would take care of that.
Now lets add the following codes to the JavaScript file..
//this would be the object shape for storing the questions
//you can change the questions to your own taste or even add more questions..
const questions = [
{
question: "How many days makes a week ?",
optionA: "10 days",
optionB: "14 days",
optionC: "5 days",
optionD: "7 days",
correctOption: "optionD"
},
{
question: "How many players are allowed on a soccer pitch ?",
optionA: "10 players",
optionB: "11 players",
optionC: "9 players",
optionD: "12 players",
correctOption: "optionB"
},
{
question: "Who was the first President of USA ?",
optionA: "Donald Trump",
optionB: "Barack Obama",
optionC: "Abraham Lincoln",
optionD: "George Washington",
correctOption: "optionD"
},
{
question: "30 days has ______ ?",
optionA: "January",
optionB: "December",
optionC: "June",
optionD: "August",
correctOption: "optionC"
},
{
question: "How manay hours can be found in a day ?",
optionA: "30 hours",
optionB: "38 hours",
optionC: "48 hours",
optionD: "24 hours",
correctOption: "optionD"
},
{
question: "Which is the longest river in the world ?",
optionA: "River Nile",
optionB: "Long River",
optionC: "River Niger",
optionD: "Lake Chad",
correctOption: "optionA"
},
{
question: "_____ is the hottest Continent on Earth ?",
optionA: "Oceania",
optionB: "Antarctica",
optionC: "Africa",
optionD: "North America",
correctOption: "optionC"
},
{
question: "Which country is the largest in the world ?",
optionA: "Russia",
optionB: "Canada",
optionC: "Africa",
optionD: "Egypt",
correctOption: "optionA"
},
{
question: "Which of these numbers is an odd number ?",
optionA: "Ten",
optionB: "Twelve",
optionC: "Eight",
optionD: "Eleven",
correctOption: "optionD"
},
{
question: `"You Can't see me" is a popular saying by`,
optionA: "Eminem",
optionB: "Bill Gates",
optionC: "Chris Brown",
optionD: "John Cena",
correctOption: "optionD"
},
{
question: "Where is the world tallest building located ?",
optionA: "Africa",
optionB: "California",
optionC: "Dubai",
optionD: "Italy",
correctOption: "optionC"
},
{
question: "The longest river in the United Kingdom is ?",
optionA: "River Severn",
optionB: "River Mersey",
optionC: "River Trent",
optionD: "River Tweed",
correctOption: "optionA"
},
{
question: "How many permanent teeth does a dog have ?",
optionA: "38",
optionB: "42",
optionC: "40",
optionD: "36",
correctOption: "optionB"
},
{
question: "Which national team won the football World cup in 2018 ?",
optionA: "England",
optionB: "Brazil",
optionC: "Germany",
optionD: "France",
correctOption: "optionD"
},
{
question: "Which US state was Donald Trump Born ?",
optionA: "New York",
optionB: "California",
optionC: "New Jersey",
optionD: "Los Angeles",
correctOption: "optionA"
},
{
question: "How man states does Nigeria have ?",
optionA: "24",
optionB: "30",
optionC: "36",
optionD: "37",
correctOption: "optionC"
},
{
question: "____ is the capital of Nigeria ?",
optionA: "Abuja",
optionB: "Lagos",
optionC: "Calabar",
optionD: "Kano",
correctOption: "optionA"
},
{
question: "Los Angeles is also known as ?",
optionA: "Angels City",
optionB: "Shining city",
optionC: "City of Angels",
optionD: "Lost Angels",
correctOption: "optionC"
},
{
question: "What is the capital of Germany ?",
optionA: "Georgia",
optionB: "Missouri",
optionC: "Oklahoma",
optionD: "Berlin",
correctOption: "optionD"
},
{
question: "How many sides does an hexagon have ?",
optionA: "Six",
optionB: "Sevene",
optionC: "Four",
optionD: "Five",
correctOption: "optionA"
},
{
question: "How many planets are currently in the solar system ?",
optionA: "Eleven",
optionB: "Seven",
optionC: "Nine",
optionD: "Eight",
correctOption: "optionD"
},
{
question: "Which Planet is the hottest ?",
optionA: "Jupitar",
optionB: "Mercury",
optionC: "Earth",
optionD: "Venus",
correctOption: "optionB"
},
{
question: "where is the smallest bone in human body located?",
optionA: "Toes",
optionB: "Ears",
optionC: "Fingers",
optionD: "Nose",
correctOption: "optionB"
},
{
question: "How many hearts does an Octopus have ?",
optionA: "One",
optionB: "Two",
optionC: "Three",
optionD: "Four",
correctOption: "optionC"
},
{
question: "How many teeth does an adult human have ?",
optionA: "28",
optionB: "30",
optionC: "32",
optionD: "36",
correctOption: "optionC"
}
]
let shuffledQuestions = [] //empty array to hold shuffled selected questions out of all available questions
function handleQuestions() {
//function to shuffle and push 10 questions to shuffledQuestions array
//app would be dealing with 10questions per session
while (shuffledQuestions.length <= 9) {
const random = questions[Math.floor(Math.random() * questions.length)]
if (!shuffledQuestions.includes(random)) {
shuffledQuestions.push(random)
}
}
}
let questionNumber = 1 //holds the current question number
let playerScore = 0 //holds the player score
let wrongAttempt = 0 //amount of wrong answers picked by player
let indexNumber = 0 //will be used in displaying next question
// function for displaying next question in the array to dom
//also handles displaying players and quiz information to dom
function NextQuestion(index) {
handleQuestions()
const currentQuestion = shuffledQuestions[index]
document.getElementById("question-number").innerHTML = questionNumber
document.getElementById("player-score").innerHTML = playerScore
document.getElementById("display-question").innerHTML = currentQuestion.question;
document.getElementById("option-one-label").innerHTML = currentQuestion.optionA;
document.getElementById("option-two-label").innerHTML = currentQuestion.optionB;
document.getElementById("option-three-label").innerHTML = currentQuestion.optionC;
document.getElementById("option-four-label").innerHTML = currentQuestion.optionD;
}
function checkForAnswer() {
const currentQuestion = shuffledQuestions[indexNumber] //gets current Question
const currentQuestionAnswer = currentQuestion.correctOption //gets current Question's answer
const options = document.getElementsByName("option"); //gets all elements in dom with name of 'option' (in this the radio inputs)
let correctOption = null
options.forEach((option) => {
if (option.value === currentQuestionAnswer) {
//get's correct's radio input with correct answer
correctOption = option.labels[0].id
}
})
//checking to make sure a radio input has been checked or an option being chosen
if (options[0].checked === false && options[1].checked === false && options[2].checked === false && options[3].checked == false) {
document.getElementById('option-modal').style.display = "flex"
}
//checking if checked radio button is same as answer
options.forEach((option) => {
if (option.checked === true && option.value === currentQuestionAnswer) {
document.getElementById(correctOption).style.backgroundColor = "green"
playerScore++ //adding to player's score
indexNumber++ //adding 1 to index so has to display next question..
//set to delay question number till when next question loads
setTimeout(() => {
questionNumber++
}, 1000)
}
else if (option.checked && option.value !== currentQuestionAnswer) {
const wrongLabelId = option.labels[0].id
document.getElementById(wrongLabelId).style.backgroundColor = "red"
document.getElementById(correctOption).style.backgroundColor = "green"
wrongAttempt++ //adds 1 to wrong attempts
indexNumber++
//set to delay question number till when next question loads
setTimeout(() => {
questionNumber++
}, 1000)
}
})
}
//called when the next button is called
function handleNextQuestion() {
checkForAnswer() //check if player picked right or wrong option
unCheckRadioButtons()
//delays next question displaying for a second just for some effects so questions don't rush in on player
setTimeout(() => {
if (indexNumber <= 9) {
//displays next question as long as index number isn't greater than 9, remember index number starts from 0, so index 9 is question 10
NextQuestion(indexNumber)
}
else {
handleEndGame()//ends game if index number greater than 9 meaning we're already at the 10th question
}
resetOptionBackground()
}, 1000);
}
//sets options background back to null after display the right/wrong colors
function resetOptionBackground() {
const options = document.getElementsByName("option");
options.forEach((option) => {
document.getElementById(option.labels[0].id).style.backgroundColor = ""
})
}
// unchecking all radio buttons for next question(can be done with map or foreach loop also)
function unCheckRadioButtons() {
const options = document.getElementsByName("option");
for (let i = 0; i < options.length; i++) {
options[i].checked = false;
}
}
// function for when all questions being answered
function handleEndGame() {
let remark = null
let remarkColor = null
// condition check for player remark and remark color
if (playerScore <= 3) {
remark = "Bad Grades, Keep Practicing."
remarkColor = "red"
}
else if (playerScore >= 4 && playerScore < 7) {
remark = "Average Grades, You can do better."
remarkColor = "orange"
}
else if (playerScore >= 7) {
remark = "Excellent, Keep the good work going."
remarkColor = "green"
}
const playerGrade = (playerScore / 10) * 100
//data to display to score board
document.getElementById('remarks').innerHTML = remark
document.getElementById('remarks').style.color = remarkColor
document.getElementById('grade-percentage').innerHTML = playerGrade
document.getElementById('wrong-answers').innerHTML = wrongAttempt
document.getElementById('right-answers').innerHTML = playerScore
document.getElementById('score-modal').style.display = "flex"
}
//closes score modal, resets game and reshuffles questions
function closeScoreModal() {
questionNumber = 1
playerScore = 0
wrongAttempt = 0
indexNumber = 0
shuffledQuestions = []
NextQuestion(indexNumber)
document.getElementById('score-modal').style.display = "none"
}
//function to close warning modal
function closeOptionModal() {
document.getElementById('option-modal').style.display = "none"
}
And that's all, you should have a fully functioning simple quiz if you correctly followed this article.
You can follow this link : https://codepen.io/Sulaimon-Olaniran/pen/zYKJLjK to see it live on Codepen.
Top comments (7)
hello I copy your quiz model impossible to make it work on my pc the form is empty even by directly copying your code I need your help if possible thank you my email address thank you
i know this is like really late. But you need to make your html outline proper. and you have to link the css page, and name the js file right and the css file right.
actuaclly is line 25 on css
"AcTuAcLlY..."
tag you should have a place where it links your JSS like this and name your Js file to quiz.js in this case. many people use app.js instead.I have a fully working version if you want to check it out on my GitHub, but it should have This Bit of code in the top and your .CSS txt doc should be called "Style.css" as in the line of code
And at the bottom of your
all that matters is that the files in your folder are named correctly to match with the links in your code. so if your file is app.js then your code should link app.js. same with any linking in general.
If you want to check out A different finished working quiz code my github link is:github.com/nickwing04/JSSchoolGame...
While youre at it check out my webpage as well: nickwing04.github.io
Pic to code template I'm talking about: imgur.com/a/pG7LnEj
i think the problem was because you forgot to post the background image. And the line 31 on css cannot work
bro you just need to link index.css file in HTML code
Thanks