I would advise javascript intermediates to work on this project. If you're trying to find better JavaScript projects. The projects in this playlist from my YouTube channel range in difficulty from beginner to sophisticated.
HTML Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MCQ Quiz</title>
<!-- Google Font -->
<!-- Stylesheet -->
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
background-color: #0a69ed;
}
.start-screen,
.score-container {
position: absolute;
top: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
button {
border: none;
outline: none;
cursor: pointer;
}
#start-button,
#restart {
font-size: 1.3em;
padding: 0.5em 1.8em;
border-radius: 0.2em;
}
#restart {
margin-top: 0.9em;
}
#display-container {
background-color: #ffffff;
padding: 3.1em 1.8em;
width: 80%;
max-width: 37.5em;
margin: 0 auto;
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border-radius: 0.6em;
}
.header {
margin-bottom: 1.8em;
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 0.6em;
border-bottom: 0.1em solid #c0bfd2;
}
.timer-div {
background-color: #e1f5fe;
width: 7.5em;
border-radius: 1.8em;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.7em 1.8em;
}
.question {
margin-bottom: 1.25em;
font-weight: 600;
}
.option-div {
font-size: 0.9em;
width: 100%;
padding: 1em;
margin: 0.3em 0;
text-align: left;
outline: none;
background: transparent;
border: 1px solid #c0bfd2;
border-radius: 0.3em;
}
.option-div:disabled {
color: #000000;
cursor: not-allowed;
}
#next-button {
font-size: 1em;
margin-top: 1.5em;
background-color: #0a69ed;
color: #ffffff;
padding: 0.7em 1.8em;
border-radius: 0.3em;
float: right;
}
.hide {
display: none;
}
.incorrect {
background-color: #ffdde0;
color: #d32f2f;
border-color: #d32f2f;
}
.correct {
background-color: #e7f6d5;
color: #689f38;
border-color: #689f38;
}
#user-score {
font-size: 1.5em;
color: #ffffff;
}
</style>
</head>
<body>
<div class="start-screen">
<button id="start-button">Start</button>
</div>
<div id="display-container">
<div class="header">
<div class="number-of-count">
<span class="number-of-question">1 of 3 questions</span>
</div>
<div class="timer-div">
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgZGF0YS1uYW1lPSJMYXllciAyIiBpZD0iTGF5ZXJfMiIgdmlld0JveD0iMCAwIDY0IDY0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojNWMzYjUxO30uY2xzLTJ7ZmlsbDojZjc0YjUwO30uY2xzLTN7ZmlsbDojZDEzZjQ0O30uY2xzLTR7ZmlsbDojOGJkOTRmO30uY2xzLTV7ZmlsbDojNDVkNGQ5O30uY2xzLTZ7ZmlsbDojMmQ5NWI1O30uY2xzLTd7ZmlsbDojMmMyYTNkO308L3N0eWxlPjwvZGVmcz48dGl0bGUvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LDUxaDZhMCwwLDAsMCwxLDAsMHY3YTMsMywwLDAsMS0zLDNoMGEzLDMsMCwwLDEtMy0zVjUxQTAsMCwwLDAsMSwxOSw1MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zOSw1MWg2YTAsMCwwLDAsMSwwLDB2N2EzLDMsMCwwLDEtMywzaDBhMywzLDAsMCwxLTMtM1Y1MUEwLDAsMCwwLDEsMzksNTFaIi8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIyMCIgY3k9IjEyIiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMjAsNmE5LDksMCwwLDEsOC44Nyw3LjVBOS4yOSw5LjI5LDAsMCwwLDI5LDEyYTksOSwwLDAsMC0xOCwwLDkuMjksOS4yOSwwLDAsMCwuMTMsMS41QTksOSwwLDAsMSwyMCw2WiIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNDQiIGN5PSIxMiIgcj0iOSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTQ0LDZhOSw5LDAsMCwxLDguODcsNy41QTkuMjksOS4yOSwwLDAsMCw1MywxMmE5LDksMCwwLDAtMTgsMCw5LjI5LDkuMjksMCwwLDAsLjEzLDEuNUE5LDksMCwwLDEsNDQsNloiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNCIgY3g9IjMyIiBjeT0iMzIiIHI9IjI0Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTUiIGN4PSIzMiIgY3k9IjMyIiByPSIyMCIvPjxwYXRoIGNsYXNzPSJjbHMtNiIgZD0iTTMyLDE1QTIwLDIwLDAsMCwxLDUxLjkyLDMzLjVjMC0uNS4wOC0xLC4wOC0xLjVhMjAsMjAsMCwwLDAtNDAsMGMwLC41MSwwLDEsLjA4LDEuNUEyMCwyMCwwLDAsMSwzMiwxNVoiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik01NywzMmEyNC44OSwyNC44OSwwLDAsMC00LjY1LTE0LjVBOS45LDkuOSwwLDAsMCw1NCwxMiwxMCwxMCwwLDAsMCwzNS4yNSw3LjIyYTI0LjEyLDI0LjEyLDAsMCwwLTYuNSwwQTEwLDEwLDAsMSwwLDExLjY1LDE3LjUsMjUsMjUsMCwwLDAsMTgsNTIuN1Y1OGE0LDQsMCwwLDAsOCwwVjU2LjI3YTI1LDI1LDAsMCwwLDEyLDBWNThhNCw0LDAsMCwwLDgsMFY1Mi43QTI1LDI1LDAsMCwwLDU3LDMyWk00NCw0YTgsOCwwLDAsMSw4LDgsNy44Miw3LjgyLDAsMCwxLTEsMy44MUEyNS4wNSwyNS4wNSwwLDAsMCwzNy4zNSw3LjU4LDgsOCwwLDAsMSw0NCw0Wk0xMiwxMkE4LDgsMCwwLDEsMjYuNjUsNy41OCwyNS4wNSwyNS4wNSwwLDAsMCwxMywxNS44MSw3LjgyLDcuODIsMCwwLDEsMTIsMTJaTTI0LDU4YTIsMiwwLDAsMS00LDBWNTMuOTJhMjQuNjQsMjQuNjQsMCwwLDAsNCwxLjc2Wm0yMCwwYTIsMiwwLDAsMS00LDBWNTUuNjhhMjQuNjQsMjQuNjQsMCwwLDAsNC0xLjc2Wk0zMiw1NUEyMywyMywwLDEsMSw1NSwzMiwyMywyMywwLDAsMSwzMiw1NVoiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik0zMiwxMUEyMSwyMSwwLDEsMCw1MywzMiwyMSwyMSwwLDAsMCwzMiwxMVptMCw0MEExOSwxOSwwLDEsMSw1MSwzMiwxOSwxOSwwLDAsMSwzMiw1MVoiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik00MiwzMUgzM1YyMmExLDEsMCwwLDAtMiwwVjMyYTEsMSwwLDAsMCwxLDFINDJhMSwxLDAsMCwwLDAtMloiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik0zMiwxNy43NGExLDEsMCwwLDAsMS0xVjE1YTEsMSwwLDAsMC0yLDB2MS43NEExLDEsMCwwLDAsMzIsMTcuNzRaIi8+PHBhdGggY2xhc3M9ImNscy03IiBkPSJNMzIsNDYuMjZhMSwxLDAsMCwwLTEsMVY0OWExLDEsMCwwLDAsMiwwVjQ3LjI2QTEsMSwwLDAsMCwzMiw0Ni4yNloiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik0yNC4zNywxNi43OGExLDEsMCwwLDAtMS43NCwxbC44OCwxLjUxYTEsMSwwLDAsMCwuODYuNSwxLDEsMCwwLDAsLjUtLjE0LDEsMSwwLDAsMCwuMzctMS4zNloiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik00MC40OSw0NC43MWExLDEsMCwwLDAtMS43MywxbC44NywxLjUxYTEsMSwwLDAsMCwxLjc0LTFaIi8+PHBhdGggY2xhc3M9ImNscy03IiBkPSJNMTkuMjksMjMuNTFsLTEuNTEtLjg4YTEsMSwwLDAsMC0xLDEuNzRsMS41MS44N2ExLDEsMCwwLDAsMS0xLjczWiIvPjxwYXRoIGNsYXNzPSJjbHMtNyIgZD0iTTQ3LjIyLDM5LjYzbC0xLjUxLS44N2ExLDEsMCwwLDAtMS4zNi4zNywxLDEsMCwwLDAsLjM2LDEuMzZsMS41MS44OGExLDEsMCwxLDAsMS0xLjc0WiIvPjxwYXRoIGNsYXNzPSJjbHMtNyIgZD0iTTE3Ljc0LDMyYTEsMSwwLDAsMC0xLTFIMTVhMSwxLDAsMCwwLDAsMmgxLjc0QTEsMSwwLDAsMCwxNy43NCwzMloiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik00OSwzMUg0Ny4yNmExLDEsMCwxLDAsMCwySDQ5YTEsMSwwLDAsMCwwLTJaIi8+PHBhdGggY2xhc3M9ImNscy03IiBkPSJNMTguMjksMzguNzZsLTEuNTEuODdhMSwxLDAsMCwwLDEsMS43NGwxLjUxLS44OGExLDEsMCwwLDAsLjM2LTEuMzZBMSwxLDAsMCwwLDE4LjI5LDM4Ljc2WiIvPjxwYXRoIGNsYXNzPSJjbHMtNyIgZD0iTTQ1LjIxLDI1LjM3YTEsMSwwLDAsMCwuNS0uMTNsMS41MS0uODdhMSwxLDAsMCwwLTEtMS43NGwtMS41MS44OGExLDEsMCwwLDAsLjUsMS44NloiLz48cGF0aCBjbGFzcz0iY2xzLTciIGQ9Ik0yNC44Nyw0NC4zNWExLDEsMCwwLDAtMS4zNi4zNmwtLjg4LDEuNTFhMSwxLDAsMCwwLDEuNzQsMWwuODctMS41MUExLDEsMCwwLDAsMjQuODcsNDQuMzVaIi8+PHBhdGggY2xhc3M9ImNscy03IiBkPSJNMzkuMTMsMTkuNjVhMSwxLDAsMCwwLC41LjE0LDEsMSwwLDAsMCwuODYtLjVsLjg4LTEuNTFhMSwxLDAsMSwwLTEuNzQtMWwtLjg3LDEuNTFBMSwxLDAsMCwwLDM5LjEzLDE5LjY1WiIvPjwvc3ZnPg==" />
<span class="time-left">10s</span>
</div>
</div>
<div id="container">
<!-- questions and options will be displayed here -->
</div>
<button id="next-button">Next</button>
</div>
<div class="score-container hide">
<div id="user-score">Demo Score</div>
<button id="restart">Restart</button>
</div>
<!-- Script -->
<script>
//References
let timeLeft = document.querySelector(".time-left");
let quizContainer = document.getElementById("container");
let nextBtn = document.getElementById("next-button");
let countOfQuestion = document.querySelector(".number-of-question");
let displayContainer = document.getElementById("display-container");
let scoreContainer = document.querySelector(".score-container");
let restart = document.getElementById("restart");
let userScore = document.getElementById("user-score");
let startScreen = document.querySelector(".start-screen");
let startButton = document.getElementById("start-button");
let questionCount;
let scoreCount = 0;
let count = 11;
let countdown;
//Questions and Options array
const quizArray = [
{
id: "0",
question: "Which is the most widely spoken language in the world?",
options: ["Spanish", "Mandarin", "English", "German"],
correct: "Mandarin",
},
{
id: "1",
question: "Which is the only continent in the world without a desert?",
options: ["North America", "Asia", "Africa", "Europe"],
correct: "Europe",
},
{
id: "2",
question: "Who invented Computer?",
options: ["Charles Babbage", "Henry Luce", "Henry Babbage", "Charles Luce"],
correct: "Charles Babbage",
},
];
//Restart Quiz
restart.addEventListener("click", () => {
initial();
displayContainer.classList.remove("hide");
scoreContainer.classList.add("hide");
});
//Next Button
nextBtn.addEventListener(
"click",
(displayNext = () => {
//increment questionCount
questionCount += 1;
//if last question
if (questionCount == quizArray.length) {
//hide question container and display score
displayContainer.classList.add("hide");
scoreContainer.classList.remove("hide");
//user score
userScore.innerHTML =
"Your score is " + scoreCount + " out of " + questionCount;
} else {
//display questionCount
countOfQuestion.innerHTML =
questionCount + 1 + " of " + quizArray.length + " Question";
//display quiz
quizDisplay(questionCount);
count = 11;
clearInterval(countdown);
timerDisplay();
}
})
);
//Timer
const timerDisplay = () => {
countdown = setInterval(() => {
count--;
timeLeft.innerHTML = `${count}s`;
if (count == 0) {
clearInterval(countdown);
displayNext();
}
}, 1000);
};
//Display quiz
const quizDisplay = (questionCount) => {
let quizCards = document.querySelectorAll(".container-mid");
//Hide other cards
quizCards.forEach((card) => {
card.classList.add("hide");
});
//display current question card
quizCards[questionCount].classList.remove("hide");
};
//Quiz Creation
function quizCreator() {
//randomly sort questions
quizArray.sort(() => Math.random() - 0.5);
//generate quiz
for (let i of quizArray) {
//randomly sort options
i.options.sort(() => Math.random() - 0.5);
//quiz card creation
let div = document.createElement("div");
div.classList.add("container-mid", "hide");
//question number
countOfQuestion.innerHTML = 1 + " of " + quizArray.length + " Question";
//question
let question_DIV = document.createElement("p");
question_DIV.classList.add("question");
question_DIV.innerHTML = i.question;
div.appendChild(question_DIV);
//options
div.innerHTML += `
<button class="option-div" onclick="checker(this)">${i.options[0]}</button>
<button class="option-div" onclick="checker(this)">${i.options[1]}</button>
<button class="option-div" onclick="checker(this)">${i.options[2]}</button>
<button class="option-div" onclick="checker(this)">${i.options[3]}</button>
`;
quizContainer.appendChild(div);
}
}
//Checker Function to check if option is correct or not
function checker(userOption) {
let userSolution = userOption.innerText;
let question =
document.getElementsByClassName("container-mid")[questionCount];
let options = question.querySelectorAll(".option-div");
//if user clicked answer == correct option stored in object
if (userSolution === quizArray[questionCount].correct) {
userOption.classList.add("correct");
scoreCount++;
} else {
userOption.classList.add("incorrect");
//For marking the correct option
options.forEach((element) => {
if (element.innerText == quizArray[questionCount].correct) {
element.classList.add("correct");
}
});
}
//clear interval(stop timer)
clearInterval(countdown);
//disable all options
options.forEach((element) => {
element.disabled = true;
});
}
//initial setup
function initial() {
quizContainer.innerHTML = "";
questionCount = 0;
scoreCount = 0;
count = 11;
clearInterval(countdown);
timerDisplay();
quizCreator();
quizDisplay(questionCount);
}
//when user click on start button
startButton.addEventListener("click", () => {
startScreen.classList.add("hide");
displayContainer.classList.remove("hide");
initial();
});
//hide quiz and display start screen
window.onload = () => {
startScreen.classList.remove("hide");
displayContainer.classList.add("hide");
};
</script>
</body>
</html>
