├── index.html
├── script.js
└── styles.css
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Quiz App
10 |
11 |
12 |
13 |
14 |
Question
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const startButton = document.getElementById('start-btn')
2 | const nextButton = document.getElementById('next-btn')
3 | const questionContainerElement = document.getElementById('question-container')
4 | const questionElement = document.getElementById('question')
5 | const answerButtonsElement = document.getElementById('answer-buttons')
6 |
7 | let shuffledQuestions, currentQuestionIndex
8 |
9 | startButton.addEventListener('click', startGame)
10 | nextButton.addEventListener('click', () => {
11 | currentQuestionIndex++
12 | setNextQuestion()
13 | })
14 |
15 | function startGame() {
16 | startButton.classList.add('hide')
17 | shuffledQuestions = questions.sort(() => Math.random() - .5)
18 | currentQuestionIndex = 0
19 | questionContainerElement.classList.remove('hide')
20 | setNextQuestion()
21 | }
22 |
23 | function setNextQuestion() {
24 | resetState()
25 | showQuestion(shuffledQuestions[currentQuestionIndex])
26 | }
27 |
28 | function showQuestion(question) {
29 | questionElement.innerText = question.question
30 | question.answers.forEach(answer => {
31 | const button = document.createElement('button')
32 | button.innerText = answer.text
33 | button.classList.add('btn')
34 | if (answer.correct) {
35 | button.dataset.correct = answer.correct
36 | }
37 | button.addEventListener('click', selectAnswer)
38 | answerButtonsElement.appendChild(button)
39 | })
40 | }
41 |
42 | function resetState() {
43 | clearStatusClass(document.body)
44 | nextButton.classList.add('hide')
45 | while (answerButtonsElement.firstChild) {
46 | answerButtonsElement.removeChild(answerButtonsElement.firstChild)
47 | }
48 | }
49 |
50 | function selectAnswer(e) {
51 | const selectedButton = e.target
52 | const correct = selectedButton.dataset.correct
53 | setStatusClass(document.body, correct)
54 | Array.from(answerButtonsElement.children).forEach(button => {
55 | setStatusClass(button, button.dataset.correct)
56 | })
57 | if (shuffledQuestions.length > currentQuestionIndex + 1) {
58 | nextButton.classList.remove('hide')
59 | } else {
60 | startButton.innerText = 'Restart'
61 | startButton.classList.remove('hide')
62 | }
63 | }
64 |
65 | function setStatusClass(element, correct) {
66 | clearStatusClass(element)
67 | if (correct) {
68 | element.classList.add('correct')
69 | } else {
70 | element.classList.add('wrong')
71 | }
72 | }
73 |
74 | function clearStatusClass(element) {
75 | element.classList.remove('correct')
76 | element.classList.remove('wrong')
77 | }
78 |
79 | const questions = [
80 | {
81 | question: 'What is 2 + 2?',
82 | answers: [
83 | { text: '4', correct: true },
84 | { text: '22', correct: false }
85 | ]
86 | },
87 | {
88 | question: 'Who is the best YouTuber?',
89 | answers: [
90 | { text: 'Web Dev Simplified', correct: true },
91 | { text: 'Traversy Media', correct: true },
92 | { text: 'Dev Ed', correct: true },
93 | { text: 'Fun Fun Function', correct: true }
94 | ]
95 | },
96 | {
97 | question: 'Is web development fun?',
98 | answers: [
99 | { text: 'Kinda', correct: false },
100 | { text: 'YES!!!', correct: true },
101 | { text: 'Um no', correct: false },
102 | { text: 'IDK', correct: false }
103 | ]
104 | },
105 | {
106 | question: 'What is 4 * 2?',
107 | answers: [
108 | { text: '6', correct: false },
109 | { text: '8', correct: true }
110 | ]
111 | }
112 | ]
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | *, *::before, *::after {
2 | box-sizing: border-box;
3 | font-family: Gotham Rounded;
4 | }
5 |
6 | :root {
7 | --hue-neutral: 200;
8 | --hue-wrong: 0;
9 | --hue-correct: 145;
10 | }
11 |
12 | body {
13 | --hue: var(--hue-neutral);
14 | padding: 0;
15 | margin: 0;
16 | display: flex;
17 | width: 100vw;
18 | height: 100vh;
19 | justify-content: center;
20 | align-items: center;
21 | background-color: hsl(var(--hue), 100%, 20%);
22 | }
23 |
24 | body.correct {
25 | --hue: var(--hue-correct);
26 | }
27 |
28 | body.wrong {
29 | --hue: var(--hue-wrong);
30 | }
31 |
32 | .container {
33 | width: 800px;
34 | max-width: 80%;
35 | background-color: white;
36 | border-radius: 5px;
37 | padding: 10px;
38 | box-shadow: 0 0 10px 2px;
39 | }
40 |
41 | .btn-grid {
42 | display: grid;
43 | grid-template-columns: repeat(2, auto);
44 | gap: 10px;
45 | margin: 20px 0;
46 | }
47 |
48 | .btn {
49 | --hue: var(--hue-neutral);
50 | border: 1px solid hsl(var(--hue), 100%, 30%);
51 | background-color: hsl(var(--hue), 100%, 50%);
52 | border-radius: 5px;
53 | padding: 5px 10px;
54 | color: white;
55 | outline: none;
56 | }
57 |
58 | .btn:hover {
59 | border-color: black;
60 | }
61 |
62 | .btn.correct {
63 | --hue: var(--hue-correct);
64 | color: black;
65 | }
66 |
67 | .btn.wrong {
68 | --hue: var(--hue-wrong);
69 | }
70 |
71 | .start-btn, .next-btn {
72 | font-size: 1.5rem;
73 | font-weight: bold;
74 | padding: 10px 20px;
75 | }
76 |
77 | .controls {
78 | display: flex;
79 | justify-content: center;
80 | align-items: center;
81 | }
82 |
83 | .hide {
84 | display: none;
85 | }
--------------------------------------------------------------------------------